2016-12-13 6 views
-1

:노드의 약속 : 사용 첫 번째/어떤 결과 (Q 라이브러리) 나는 완료 약속의 수를 기다렸다가 약속의 결과에 해당하는 값 목록 작업을 쉽게 년대 <code>Q</code> 라이브러리를 사용하여 이해

Q.all([ 
    promise1, 
    promise2, 
    . 
    . 
    . 
    promiseN, 
]).then(results) { 
    // results is a list of all the values from 1 to n 
}); 

그러나 단 하나의, 가장 빠른 완성도의 결과에만 관심이 있다면 어떻게됩니까? 유스 케이스를 제공하려면 : 큰 파일 목록을 검토하는 데 관심이 있고 "짐바브웨"라는 단어가 포함 된 파일을 찾으면 곧 만족합니다.

나는 이런 식으로 작업을 수행 할 수 있습니다

Q.all(fileNames.map(function(fileName) { 
    return readFilePromise(fileName).then(function(fileContents) { 
     return fileContents.contains('zimbabwe') ? fileContents : null; 
    })); 
})).then(function(results) { 
    var zimbabweFile = results.filter(function(r) { return r !== null; })[0]; 
}); 

하지만 난 이미 "짐바브웨"발견 한 경우에도 모든 파일을 처리 할 때 필요합니다. "짐바브웨"가 들어있는 2kb 파일과 "짐바브웨"가 들어 있지 않은 30tb 파일이있는 경우 (그리고 파일을 비동기식으로 읽는다고 가정합니다) - 바보입니다! "짐바브웨는"발견 된 경우 내 30TB 파일에서 대기하지 않습니다이 방법

Q.any(fileNames.map(function(fileName) { 
    return readFilePromise(fileName).then(function(fileContents) { 
     if (fileContents.contains('zimbabwe')) return fileContents; 
     /* 
     Indicate failure 
     -Return "null" or "undefined"? 
     -Throw error? 
     */ 
    })); 
})).then(function(result) { 
    // Only one result! 
    var zimbabweFile = result; 
}).fail(function() { /* no "zimbabwe" found */ }); 

: 내가 할 수 있기를 원하는 것은

는 값 어떤 약속이 충족되는 순간을 얻을 수있다 내 2kb 파일을 일찍.

그러나 Q.any과 같은 것은 없습니다!

질문 : 어떻게해야합니까?

중요 사항 : 내부 약속 중 하나에서 오류가 발생하더라도 오류없이 반환되어야합니다.

참고 : 첫 번째 유효한 값을 찾을 때 오류가 발생하여 Q.all을 해킹 할 수 있음을 알고 있지만이를 피하기를 원합니다.

참고 : Q.any과 같은 동작이 잘못되었거나 부적절 할 수 있음을 알고 있습니다. 유효한 유스 케이스가 있다고 믿으십시오!

+0

Q가 지원한다면 당연히 몰라.하지만 본래의 약속은 확실히 그렇습니다. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race –

+0

@KevinB 좋은 지적, 고정! Q와 기본 약속을 혼합하는 것이 좋지 않다고 생각합니까? 이것에 대한 합의가 무엇인지 아십니까? –

+0

@KevinB 다른 뉴스에서 실제로 Q.race와 같은 것이 있습니다 - 문서화되지 않았지만 존재합니다. 답변을 추가하면 수표를드립니다! –

답변

1

경주와 취소의 두 가지 문제가 있습니다.

레이싱은 Promise.race 또는 좋아하는 약속 라이브러리에서 사용할 수 있습니다. 원하는 경우 약 두 줄로 직접 쓸 수 있습니다.

function race(promises) { 
    return new Promise((resolve, reject) => 
    promises.forEach(promise => promise.then(resolve, reject))); 
} 

약속이 거부되면 거부합니다. 대신 경우에 당신은 당신이 내가 여기에 가지 않을 Promise.all, 함께 promise inversion trick을 사용할 수, 거부를 건너 뛰려면, 모든 약속을 거부하는 경우에만 거부, 다음

function race(promises) { 
    let rejected = 0; 
    return new Promise((resolve, reject) => 
    promises.forEach(promise => promise.then(resolve, 
    () => { if (++rejected === promises.length) reject(); } 
    ); 
} 

을 또는.

당신의 실제 문제는 다릅니다. 다른 어떤 문제가 해결 될 때 다른 약속을 "취소"하려는 것 같습니다. 이를 위해서는 추가 특수 기계류가 필요합니다. 처리의 각 세그먼트를 나타내는 객체는 종료하도록 요청할 수있는 방법이 필요합니다.

class Processor { 
    promise() { ... } 
    terminate() { ... } 
} 

지금 당신은 그들이 몇 년에서 구현 될 때이 쉽게 할 수있는 약속 취소를 처리하기 위해 다양한 제안이 있습니다

function race(processors) { 
    let rejected = 0; 
    return new Promise((resolve, reject) => 
    processors.forEach(processor => processor.promise().then(
    () => { 
     resolve(); 
     processors.forEach(processor => processor.terminate()); 
     }, 
    () => { if (++rejected === processors.length) reject(); } 
    ); 
); 
} 

으로 인종의 버전을 작성할 수 있습니다 여기에 몇 가지 의사 코드는 .