2015-01-21 3 views
84

MDN에서 보니 then()에 전달 된 values은 Promise.all의 콜백에 약속의 순서대로 값이 들어 있습니다. 예를 들어 :Promise.all : 해결 된 값의 순서

var somePromises = [1, 2, 3, 4, 5].map(Promise.resolve); 
return Promise.all(somePromises).then(function(results) { 
    console.log(results) // is [1, 2, 3, 4, 5] the guaranteed result? 
}); 

는 사람이있는에 values해야 주문할 내용의 사양을 인용 수 있습니까?

PS : 같은 실행 코드는 물론 아무런 증거가 없음에도 불구하고이 사실로 보인다 것을 보여 주었다 - 그것은이었다 우연의 일치를 가질 수있다.

답변

117

곧, 순서는을 보존됩니다. 당신이 연결 사양에 따라

, Promise.all(iterable)이 취하는 iterable (즉, Iterator 인터페이스를 지원하는 개체)를 매개 변수로 나중에 iterable 이상 후자 루프 IteratorStep(iterator)를 사용하여 전화 그것으로 PerformPromiseAll(iterator, constructor, resultCapability)에 있습니다.
이것은 당신이 Promise.all()에 전달하는 반복 가능한 엄격하게 주문하는 경우 경우, 그들은 여전히 ​​한 번에 통과 주문을 의미합니다.

해결 각 해결 약속 인덱스를 표시하는 내부 [[Index]] 슬롯을 가지고 Promise.all() Resolve를 통해 구현된다

원래의 입력에서 약속의


이 모든 것은 입력이 엄격하게 정렬 된 경우 (예 : 배열) 출력이 입력으로 엄격하게 정렬됨을 의미합니다. 이미 배열에 대응하여, Promise.all 집계 모든 해결 값을 언급 한 이전의 답변으로

// Used to display results 
 
const write = msg => { 
 
    document.body.appendChild(document.createElement('div')).innerHTML = msg; 
 
}; 
 

 
// Different speed async operations 
 
const slow = new Promise(resolve => { 
 
    setTimeout(resolve, 200, 'slow'); 
 
}); 
 
const instant = 'instant'; 
 
const quick = new Promise(resolve => { 
 
    setTimeout(resolve, 50, 'quick'); 
 
}); 
 

 
// The order is preserved regardless of what resolved first 
 
Promise.all([slow, instant, quick]).then(responses => { 
 
    responses.map(response => write(response)); 
 
});

+0

iterable은 어떻게 엄격하게 정렬되지 않습니까? 모든 반복 가능 항목은 값을 생성하는 순서에 따라 "엄격하게 정렬"됩니다. –

+0

주 - Firefox는 약속의 iterables를 올바르게 구현하는 유일한 브라우저입니다. Chrome은'Promise.all '에 반복 실행 가능 코드를 전달하면 현재'excute '를 throw합니다. 또한 iterables를 전달하는 것을 지원하는 사용자 영역 약속 구현에 대해서는 아직 알지 못합니다. 많은 사람들이 그것을 토론하고 그 시점에 반대하기로 결정했습니다. –

+0

@BenjaminGruenbaum'Object'는 (엄격하게 명령되지 않았기 때문에) 기본 반복 동작을 가지고 있지 않습니다. 즉, iterable 인터페이스를 제공하는 것과 함께 사용할 경우 구현에 따라 순서가 모호 할 수 있습니다. – Nit

19

예, results있는 숫자는 promises와 동일한 순서이다.

사용 된 반복기 API 및 일반 약속 생성자로 인해 다소 복잡하지만, ES6 spec on Promise.all을 인용 할 수 있습니다. 그러나 각 resolver 콜백에는 promise-array 반복에서 생성되고 결과 배열의 값을 설정하는 데 사용되는 [[index]] 속성이 있습니다.

+2

정말 확실하지 않은 이유는 downvoted되었다. –

+0

이상한, 오늘은 출력 순서가 먼저 해결 된 사람에 의해 결정되었다고 말하면서 YouTube 비디오를 보았고 그 다음에 두 번째로 ..... 비디오 OP가 잘못되었다고 생각합니까? –

+1

@RoyiNamir : 그는 분명히있었습니다. – Bergi

1

: 당신은 아래의 바이올린 (ES6)에서 행동에서 볼 수

원래 약속의 입력 순서 (Aggregating Promises 참조).

그러나 클라이언트 측에서만 순서가 유지된다는 점을 지적하고자합니다.

개발자에게는 약속이 성취 된 것으로 보이지만 사실상 약속은 다른 속도로 처리됩니다. 백엔드가 약속을 다른 순서로받을 수 있기 때문에 원격 백엔드로 작업 할 때를 아는 것이 중요합니다.

을 약속 : 여기

는 시간 제한 사용하여 문제를 보여주는 예이다.코드의 모든

const myPromises = [ 
 
    new Promise((resolve) => setTimeout(() => {resolve('A (slow)'); console.log('A (slow)')}, 1000)), 
 
    new Promise((resolve) => setTimeout(() => {resolve('B (slower)'); console.log('B (slower)')}, 2000)), 
 
    new Promise((resolve) => setTimeout(() => {resolve('C (fast)'); console.log('C (fast)')}, 10)) 
 
]; 
 

 
Promise.all(myPromises).then(console.log)

위와 같이, 세 프라 (A, B, C)를 Promise.all 주어진다. 3 가지 약속은 서로 다른 속도로 실행됩니다 (C가 가장 빠르며 B가 가장 느림).

C (fast) 
A (slow) 
B (slower) 

을 약속 AJAX 다음 원격 백엔드이 순서대로 값을 받게됩니다 호출하는 경우 : 약속의 console.log 문이 순서에 표시하는 이유입니다. 그러나 클라이언트 측에서 Promise.all은 결과가 myPromises 어레이의 원래 위치에 따라 정렬되도록합니다. 최종 결과가 이유입니다 :

['A (slow)', 'B (slower)', 'C (fast)'] 

당신은 또한 당신의 약속의 실제 실행을 보장하려면

는, 당신은 약속 큐와 같은 개념을해야합니다. 여기 p-queue를 사용하는 예입니다 (주의, 당신은 기능의 모든 약속을 포장 할 필요) :

순차 약속 큐

const PQueue = require('p-queue'); 
const queue = new PQueue({concurrency: 1}); 

// Thunked Promises: 
const myPromises = [ 
() => new Promise((resolve) => setTimeout(() => { 
    resolve('A (slow)'); 
    console.log('A (slow)'); 
    }, 1000)), 
() => new Promise((resolve) => setTimeout(() => { 
    resolve('B (slower)'); 
    console.log('B (slower)'); 
    }, 2000)), 
() => new Promise((resolve) => setTimeout(() => { 
    resolve('C (fast)'); 
    console.log('C (fast)'); 
    }, 10)) 
]; 

queue.addAll(myPromises).then(console.log); 

결과

A (slow) 
B (slower) 
C (fast) 

['A (slow)', 'B (slower)', 'C (fast)'] 
+1

좋은 답변, expecially PQueue 사용 – ironstein