data await async all javascript promise es6-promise

javascript - await - Promise.all: orden de valores resueltos



promise.all foreach (3)

Como ya se indicó en las respuestas anteriores, Promise.all agrega todos los valores resueltos con una matriz correspondiente al orden de entrada de las Promesas originales (consulte Agregación de promesas ).

Sin embargo, me gustaría señalar que el pedido solo se conserva en el lado del cliente.

Para el desarrollador, parece que las promesas se cumplieron en orden, pero en realidad, las promesas se procesan a diferentes velocidades. Es importante saber cuándo trabaja con un servidor remoto porque el servidor podría recibir sus promesas en un orden diferente.

Aquí hay un ejemplo que demuestra el problema mediante el uso de tiempos de espera:

Promesa.todos

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)

En el código que se muestra arriba, se otorgan tres Promesas (A, B, C) a Promise.all . Las tres promesas se ejecutan a diferentes velocidades (C es la más rápida y B la más lenta). Es por eso que las declaraciones console.log de las Promesas aparecen en este orden:

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

Si las Promesas son llamadas AJAX, un servidor remoto recibirá estos valores en este orden. Pero en el lado del cliente, Promise.all garantiza que los resultados se ordenan de acuerdo con las posiciones originales de la matriz myPromises . Por eso el resultado final es:

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

Si desea garantizar también la ejecución real de sus Promesas, necesitaría un concepto como una cola Promesa. Aquí hay un ejemplo usando p-queue (tenga cuidado, necesita ajustar todas las promesas en las funciones):

Cola de promesa secuencial

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

Resultado

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

Al mirar MDN , parece que los values pasados ​​a la devolución de llamada then() de Promise.all contienen los valores en el orden de las promesas. Por ejemplo:

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

¿Alguien puede citar una especificación que indique en qué orden deben estar los values ?

PD: Ejecutar un código como ese mostró que esto parece ser cierto, aunque eso no es una prueba, podría haber sido una coincidencia.


En breve, se conserva el orden .

Siguiendo la especificación a la que se vinculó, Promise.all(iterable) toma un iterable (es decir, un objeto que admite la interfaz Iterator ) como parámetro y luego llama a PerformPromiseAll( iterator, constructor, resultCapability) con él, donde el último bucle sobre iterable usando IteratorStep(iterator) .
Esto significa que si el iterable que pasa a Promise.all() está estrictamente ordenado, aún se ordenarán una vez que se lo pase.

La resolución se implementa a través de Promise.all() Resolve donde cada promesa resuelta tiene una ranura interna [[Index]] , que marca el índice de la promesa en la entrada original.

Todo esto significa que la salida está estrictamente ordenada como entrada, siempre que la entrada esté estrictamente ordenada (por ejemplo, una matriz).

Puede ver esto en acción en el siguiente violín (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)); });


Sí, los valores en los results están en el mismo orden que las promises .

Se podría citar la especificación ES6 en Promise.all , aunque es un poco complicado debido a la API de iterador utilizada y al constructor de promesa genérico. Sin embargo, notará que cada devolución de llamada de resolución tiene un atributo [[index]] que se crea en la iteración de matriz de promesa y se utiliza para establecer los valores en la matriz de resultados.