Promise.all: Ordem dos valores resolvidos

Observando o MDN , parece que os values passados ​​para o callback then() do Promise.all contém os valores na ordem das promises. Por exemplo:

 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? }); 

Alguém pode citar uma especificação indicando em qual ordem os values devem estar?

PS: A execução de código como esse mostrou que isso parece ser verdade, embora isso não seja uma prova – poderia ter sido coincidência.

Logo, a ordem é preservada .

Seguindo a especificação que você vinculou, Promise.all(iterable) leva um iterable (isto é, um object que suporta a interface Iterator ) como um parâmetro e posteriormente em chamadas PerformPromiseAll( iterator, constructor, resultCapability) com ele, onde os últimos loops mais iterable usando IteratorStep(iterator) .
Isso significa que se o iterável que você passar para Promise.all() for estritamente ordenado, eles ainda serão ordenados depois de serem passados.

Resolvendo é implementado via Promise.all() Resolve onde cada promise resolvida tem um slot [[Index]] interno, que marca o índice da promise na input original.


Tudo isso significa que a saída é estritamente ordenada como a input, desde que a input seja estritamente ordenada (por exemplo, uma matriz).

Você pode ver isso em ação no violino abaixo (ES6):

 // 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)); }); 

Sim, os valores nos results estão na mesma ordem das promises .

Pode-se citar a especificação do ES6 no Promise.all , embora seja um pouco confuso devido ao iterador api usado e ao construtor de promise genérica. No entanto, você notará que cada callback do resolvedor tem um atributo [[index]] que é criado na iteração da matriz de promises e usado para definir os valores na matriz de resultados.

Como as respostas anteriores já afirmaram, o Promise.all agrega todos os valores resolvidos com uma matriz correspondente à ordem de input das Promessas originais (consulte Agregar Promessas ).

No entanto, gostaria de salientar que o pedido só é preservado no lado do cliente!

Para o desenvolvedor, parece que as Promessas foram cumpridas em ordem, mas, na realidade, as Promessas são processadas em velocidades diferentes. É importante saber quando você trabalha com um back-end remoto porque o backend pode receber suas promises em uma ordem diferente.

Aqui está um exemplo que demonstra o problema usando tempos limite:

Promise.all

 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)