2017-11-16 1 views
0

가장 쉬운 방법은 package.json에서 모든 패키지를 검색하고 npm 레지스트리를 사용하여 새 업데이트가 있는지 확인하는 것입니다. 나는 그것의 대부분을했다. 루프를 위해 다음 사항을 수락 :반응이 많은 약속에서 이것을 처리하는 방법을 잘 모르는 경우

import request from 'request' 

export const findAllUpdates = (packageInfo) => { 
    for(prop in packageInfo) { 
    request('https://registry.npmjs.org/' + prop, function(err, resp) { 
     json = JSON.parse(resp.body); 

     if (json['dist-tags'].latest !== packageInfo[prop].version) { 
     // Do something, we are not the same version so we should 
     // update some counter. 
     } 
    }); 
    } 
} 

귀하의 packageInfo을 종속성 또는 package.json과 패키지 lock.json 또는 yarn.lock에서 dev에 의존성 중 하나를 나타냅니다 key=>value의 객체가되어

중요한 부분은 위의 함수에서 설치 한 것입니다. 그런 다음 레지스트리를 사용하여 패키지 정보를 얻은 다음 레지스트리의 최신 버전을 설치 한 후 가장 이상적으로 비교합니다 총 카운트로 구성 요소의 상태를 업데이트합니다.

어떤 문제가 우리가 콜백 지옥을 입력했는지, 특히 for 루프를 사용하여 모든 패키지를 루핑하여 요청을하는 경우가 있습니다.

요청을 한 후에도 변수에 액세스 할 수 없으므로 변수를 만들고 거기에 응답을 저장할 수 없습니다. 당신이 40 개의 패키지를 dep 또는 dev로 설치하고 많은 이벤트를 발생시킬 수 있기 때문에 여기서 이벤트를 사용하는 것이 어떻게되는지 알 수 없습니다.

마지막으로 적절한 해결책은 약속을 사용하는 것일 수 있지만 약속의 전체 개념은 .then(() => {}), .catch(() => {})과 함께 콜백이 더 많아 나를 사각으로 돌려 놓습니다.

목표는 구성 요소에이를 호출하고 해당 구성 요소의 상태가

어떤 아이디어를 업데이트 (또는 적어도 새로운 버전이)해야 할 패키지의 총량으로 업데이트하는 것입니다? 나는이 모든 잘못을 저지르고 있는가?

답변

1

당신은 약속을 바라 보는 것이 옳습니다.

가장 먼저 할 일은 request의 약속 가능 버전을 제공하는 것입니다. util에는 Node-callback-style 함수를 사용하고 약속 가능 버전을 반환하는 promisify 함수가 있습니다. 그래서 :

import util from 'util'; 
// ... 
const prequest = util.promisify(request); 

배열의 약속을 수집 (그리고 그들에 then를 사용하여 귀하의 요청을, 다음 (모두 한 번에 전체 API를 할 수있는 NPM 모듈, promisify도있다.) 후 처리를 수행하려면 then은 새로운 약속을 반환하므로 여전히 양호합니다.) Promise.all을 사용하여 모두 해결 될 때까지 (또는 거부 할 때까지) 기다립니다. 그래서 모두 함께

는 : 그들 중 하나가 거부 할 경우

전체 기능의 약속 (순서대로) 배열의 각 약속의 결과의 배열에 해결할 수 있다고
import request from 'request'; 
import util from 'util'; 

const prequest = util.promisify(request); 

export const findAllUpdates = (packageInfo) => { 
    const updates = [] 
    for (const prop in packageInfo) { 
    updates.push(prequest('https://registry.npmjs.org/' + prop).then(resp => { 
     const json = JSON.parse(resp.body); 

     if (json['dist-tags'].latest !== packageInfo[prop].version) { 
     // Do something, we are not the same version so we should 
     // update some counter. 
     } 

     // Perhaps return something here, it will be the resolution 
     // for the promise for this request; otherwise, the promise 
     // will resolve with `undefined`. 
    })); 
    } 
    return Promise.all(updates); 
}; 

, 또는 (다시는) 거부합니다.

나는 async/await을 제안 할 수 있기를 원하지만 현재는 여러 가지 약속이 많지 않습니다. (await.all 가끔 이하는 일을하는 이야기가 있었지만 [아직?]에 걸리지 않았습니다.)

는 우리가 물건을 조금 어기면하지만, 그것은 async/await와 조금 좋네요했다 가졌 :

import request from 'request'; 
import util from 'util'; 

const prequest = util.promisify(request); 

const checkOne = async (prop) => { 
    const resp = await prequest('https://registry.npmjs.org/' + prop); 
    const json = JSON.parse(resp.body); 
    if (json['dist-tags'].latest !== packageInfo[prop].version) { 
    // Do something, we are not the same version so we should 
    // update some counter. 
    } 

    // Perhaps return something here, it will be the resolution 
    // for the promise for this request; otherwise, the promise 
    // will resolve with `undefined`. 
}; 

export const findAllUpdates = (packageInfo) => { 
    const updates = [] 
    for (const prop in packageInfo) { 
    updates.push(checkOne(prop); 
    } 
    return Promise.all(updates); 
}; 

그리고 물론

packageInfo의 모든 속성을 "소유"속성 경우 findAllUpdates 많이 간단 취득 (상속되지 않음) :

export const findAllUpdates = (packageInfo) => { 
    return Promise.all(Object.keys(packageInfo).map(checkOne)); 
}; 

사이드 노트 : 나는 몇 가지 누락 된 선언을 추가 한 abov 이자형.

0

Promise를 사용하는 것이 좋습니다. 여러 개의 비동기 호출을 수행 한 다음 Promise.all을 사용하여 대기 할 수 있습니다.

또한 "findAllUpdates"메서드에서 Promise를 반환하면 정보를 사용할 수있을 때 발신자가 자신의 상태를 쉽게 업데이트 할 수 있습니다. 그 약속을 사용하여 아래에 내가 간단한 예제를 만들었습니다

findAllUpdates(..) 
    .then(result => this.setState({ 
    packagesNeedUpdate: result.filter(p => !p.latest).length 
    })); 

:

에서 같은 그 것이 뭔가를 반응한다. 그것은 요청을 위조하지만 그렇지 않으면 꽤 정확해야합니다.

// Fake requests. Will return version '1.0.0' after one second. 
 
const makeRequest = url => { 
 
    return new Promise(resolve => { 
 
    setTimeout(() => { 
 
     resolve(JSON.stringify({ 
 
     'dist-tags': { 
 
      'latest': '1.0.0' 
 
     } 
 
     }, null, 2)); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
const findAllUpdates = (packageInfo) => { 
 
    return new Promise(resolve => { 
 
    const promises = Object.keys(packageInfo) 
 
     .map(prop => makeRequest('https://registry.npmjs.org/' + prop).then(JSON.parse)); 
 
     
 
    Promise.all(promises) // Wait for all promises 
 
     .then(jsons => { 
 
     const results = Object.keys(packageInfo) 
 
      .map((prop, i) => { 
 
      const latestInNpm = jsons[i]['dist-tags'].latest; 
 
      const current = packageInfo[prop].version 
 
      return { 
 
       prop, 
 
       latest: latestInNpm === current 
 
      } 
 
      }); 
 
     resolve(results); // Return result to caller 
 
     }); 
 
    }); 
 
} 
 

 
function run() { 
 
    console.log('Loading..'); 
 
    
 
    const packages = { 
 
    'react': {version: '0.0.1'}, 
 
    'angular': {version: '1.0.0'}, 
 
    'ember': {version: '0.5.0'}, 
 
    'mithril': {version: '0.9.0'} 
 
    }; 
 
    
 
    findAllUpdates(packages).then(result => { 
 
    const needUpdates = result.filter(p => !p.latest).length; 
 
    console.log('Need updates: ', needUpdates); 
 
    }); 
 
} 
 

 
run();

관련 문제