Me gustaría aclarar este punto, ya que la documentación no es muy clara al respecto;
P1: ¿Se Promise.all(iterable)
procesan todas las promesas de forma secuencial o en paralelo? O, más específicamente, ¿es el equivalente a ejecutar promesas encadenadas como
p1.then(p2).then(p3).then(p4).then(p5)....
o se trata de otro tipo de algoritmo donde todos p1
, p2
, p3
, p4
, p5
, etc., están siendo llamados al mismo tiempo (en paralelo) y los resultados son devueltos tan pronto como todos determinación (o se rechaza)?
P2: Si se Promise.all
ejecuta en paralelo, ¿hay una manera conveniente de ejecutar una secuencia iterable?
Nota : No quiero usar Q, o Bluebird, sino todas las especificaciones nativas de ES6.
javascript
node.js
promise
es6-promise
Yanick Rochon
fuente
fuente
Promise.all
ejecuta en paralelo.node.js
yio.js
ya que aquí es donde lo estoy usando. Entonces, sí, la implementación de V8 si se quiere.Promise.all
.new Promise(a).then(b); c();
a se ejecuta primero, luego c, luego b. No es Promise.todo lo que ejecuta estas promesas, solo se maneja cuando se resuelven.Respuestas:
No, las promesas no pueden "ejecutarse". Comienzan su tarea cuando se están creando , solo representan los resultados, y usted está ejecutando todo en paralelo incluso antes de pasarlos
Promise.all
.Promise.all
solo espera múltiples promesas. No le importa en qué orden resuelven, o si los cálculos se ejecutan en paralelo.Si ya tienes tus promesas, no puedes hacer mucho pero
Promise.all([p1, p2, p3, …])
(que no tiene una noción de secuencia). Pero si tiene un iterable de funciones asincrónicas, puede ejecutarlas secuencialmente. Básicamente necesitas llegar dea
y la solución para hacer eso es usar
Array::reduce
:fuente
then
secuencia: el valor de retorno es la promesa para el últimofn
resultado, y puede encadenar otras devoluciones de llamada a eso.fn1().then(p2).then(fn3).catch(…
? No es necesario usar una expresión de función.retValFromF1
se pasap2
, eso es exactamente lo quep2
hace. Claro, si desea hacer más (pasar variables adicionales, llamar a múltiples funciones, etc.) debe usar una expresión de función, aunque cambiarp2
en la matriz sería más fáciliterable
es la[fn1, fn2, fn3, …]
matrizEn paralelo
Ventajas: más rápido. Todas las iteraciones se ejecutarán incluso si una falla.
En secuencia
Ventajas: las variables en el bucle pueden ser compartidas por cada iteración. Se comporta como un código síncrono imperativo normal.
fuente
for (const item of items) await fetchItem(item);
await Promise.all(items.map(async item => { return await fetchItem(item).catch(e => e) }))
async
función es una llamada API y no desea DDOS al servidor. Tiene un mejor control sobre los resultados individuales y los errores arrojados en la ejecución. Aún mejor, puede decidir qué errores continuar y qué romper el ciclo.La respuesta de Bergis me puso en el camino correcto usando Array.reduce.
Sin embargo, para que las funciones devuelvan mis promesas de ejecutarse una tras otra, tuve que agregar un poco más de anidamiento.
Mi caso de uso real es una matriz de archivos que necesito transferir en orden uno tras otro debido a los límites posteriores ...
Aquí es con lo que terminé.
Como sugieren las respuestas anteriores, usando:
no esperó a que se completara la transferencia antes de comenzar otra y también el texto "Todos los archivos transferidos" llegó incluso antes de que se iniciara la primera transferencia de archivos.
No estoy seguro de lo que hice mal, pero quería compartir lo que funcionó para mí.
Editar: desde que escribí esta publicación, ahora entiendo por qué la primera versión no funcionó. then () espera que una función devuelva una promesa. Por lo tanto, debe pasar el nombre de la función sin paréntesis. Ahora, mi función quiere un argumento, ¡entonces necesito envolverme en una función anónima sin tomar ningún argumento!
fuente
solo para elaborar sobre la respuesta de @ Bergi (que es muy sucinta, pero difícil de entender;)
Este código ejecutará cada elemento de la matriz y agregará la siguiente 'cadena' al final;
Espero que tenga sentido.
fuente
También puede procesar un iterable secuencialmente con una función asíncrona utilizando una función recursiva. Por ejemplo, dada una matriz
a
para procesar con función asincrónicasomeAsyncFunction()
:fuente
array.prototype.reduce
es mucho mejor en términos de rendimiento que una función recursivareduce
donde tiene que construir toda lathen()
cadena en un solo paso y luego ejecutar.NodeJS no ejecuta promesas en paralelo, las ejecuta simultáneamente, ya que se trata de una arquitectura de bucle de eventos de subproceso único. Existe la posibilidad de ejecutar cosas en paralelo creando un nuevo proceso hijo para aprovechar la CPU de múltiples núcleos.
Paralelo contra Concurrente
De hecho, lo que
Promise.all
hace es apilar la función de promesas en la cola apropiada (ver arquitectura de bucle de eventos) ejecutándolas simultáneamente (llamar a P1, P2, ...) y luego esperar cada resultado, luego resolver Promise.all con todas las promesas resultados. Promise.all fallará en la primera promesa que falle, a menos que usted mismo haya logrado el rechazo.Existe una gran diferencia entre paralelo y concurrente, el primero ejecutará un cálculo diferente en un proceso separado exactamente al mismo tiempo y progresará en ese mismo ritmo, mientras que el otro ejecutará el cálculo diferente uno tras otro sin esperar al anterior cálculo para terminar y progresar al mismo tiempo sin depender el uno del otro.
Finalmente, para responder a su pregunta,
Promise.all
no se ejecutará ni en paralelo ni secuencialmente, sino al mismo tiempo.fuente
El uso de async espera una serie de promesas que se pueden ejecutar fácilmente de forma secuencial:
Nota: en la implementación anterior, si se rechaza una promesa, el resto no se ejecutará. Si desea que se ejecuten todas sus promesas, envuelva su
await a[i]();
interiortry catch
fuente
paralela
mira este ejemplo
al ejecutar el código, consolará "CALLED" para las seis promesas y cuando se resuelvan, consolará cada 6 respuestas después del tiempo de espera al mismo tiempo
fuente
La respuesta de Bergi me ayudó a hacer que la llamada fuera síncrona. He agregado un ejemplo a continuación donde llamamos a cada función después de que se llama a la función anterior.
fuente
Puedes hacerlo por bucle.
promesa de devolución de función asíncrona
si escribe el siguiente código, el cliente se crea paralelamente
entonces todos los clientes se crean paralelamente. pero si desea crear un cliente secuencialmente, debe usar for loop
entonces todos los clientes se crean secuencialmente.
feliz codificación :)
fuente
async
/await
solo está disponible con un transpilador o con otros motores que nodos. Además, realmente no se debe mezclarasync
conyield
. Cuando actúan de la misma manera con un transpiladorco
, realmente son bastante diferentes y normalmente no deberían sustituirse entre sí. Además, debe mencionar estas restricciones ya que su respuesta es confusa para los programadores novatos.He estado usando para para resolver promesas secuenciales. No estoy seguro de si ayuda aquí, pero esto es lo que he estado haciendo.
fuente
Esto podría responder parte de su pregunta.
sí, puede encadenar una serie de funciones de devolución de promesa de la siguiente manera ... (esto pasa el resultado de cada función a la siguiente). por supuesto, podría editarlo para pasar el mismo argumento (o ningún argumento) a cada función.
fuente
Me topé con esta página mientras intentaba resolver un problema en NodeJS: reensamblaje de fragmentos de archivos. Básicamente: tengo una variedad de nombres de archivo. Necesito agregar todos esos archivos, en el orden correcto, para crear un archivo grande. Debo hacer esto asincrónicamente.
El módulo 'fs' de Node proporciona appendFileSync pero no quise bloquear el servidor durante esta operación. Quería usar el módulo fs.promises y encontrar una manera de encadenar todo esto. Los ejemplos en esta página no funcionaron para mí porque realmente necesitaba dos operaciones: fsPromises.read () para leer en el fragmento de archivo y fsPromises.appendFile () para concatenar con el archivo de destino. Tal vez si fuera mejor con javascript podría haber hecho que las respuestas anteriores funcionen para mí. ;-)
Me topé con esto ... https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/ ... y pude hackear juntos una solución de trabajo.
TLDR:
Y aquí hay una prueba de unidad de jazmín para ello:
Espero que esto ayude a alguien.
fuente