¿Promise.all nativo de Node.js se procesa en paralelo o secuencialmente?

Resuelto Yanick Rochon asked hace 9 años • 14 respuestas

Me gustaría aclarar este punto, ya que la documentación no es demasiado 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 es algún otro tipo de algoritmo en el que todos p1,,,,,, p2etc. se llaman al mismo tiempo (en paralelo) y los resultados se devuelven tan pronto como todos se resuelven (o uno rechaza) p3?p4p5

P2: Si Promise.allse ejecuta en paralelo, ¿existe una manera conveniente de ejecutar un iterable secuencialmente?

Nota : No quiero usar Q ni Bluebird, sino todas las especificaciones nativas de ES6.

Yanick Rochon avatar Jun 14 '15 04:06 Yanick Rochon
Aceptado

¿ Está Promise.all(iterable)cumpliendo todas las promesas?

No, las promesas no pueden "ejecutarse". Comienzan su tarea cuando se crean (representan sólo los resultados) y usted ejecuta todo en paralelo incluso antes de pasarlos a Promise.all.

Promise.allsólo espera múltiples promesas. No importa en qué orden se resuelven o si los cálculos se ejecutan en paralelo.

¿Existe una forma conveniente de ejecutar un iterable secuencialmente?

Si ya tienes tus promesas, no puedes hacer mucho más Promise.all([p1, p2, p3, …])(lo cual no tiene noción de secuencia). Pero si tiene un iterable de funciones asincrónicas, puede ejecutarlas secuencialmente. Básicamente necesitas llegar desde

[fn1, fn2, fn3, …]

a

fn1().then(fn2).then(fn3).then(…)

y la solución para hacerlo es usar Array::reduce:

iterable.reduce((p, fn) => p.then(fn), Promise.resolve())
Bergi avatar Jun 13 '2015 21:06 Bergi

En paralelo

await Promise.all(items.map(async (item) => { 
  await fetchItem(item) 
}))

Ventajas: Más rápido. Todas las iteraciones se iniciarán incluso si una falla más adelante. Sin embargo, "fallará rápidamente" . Utilice Promise.allSettled, para completar todas las iteraciones en paralelo, incluso si algunas arrojan. Técnicamente, se trata de invocaciones simultáneas, no en paralelo.

En secuencia

for (const item of items) {
  await fetchItem(item)
}

Ventajas: las variables del bucle se pueden compartir en cada iteración. Se comporta como código síncrono imperativo normal.

david_adler avatar Sep 07 '2017 00:09 david_adler

NodeJS no ejecuta promesas en paralelo, las ejecuta simultáneamente ya que es una arquitectura de bucle de eventos de un solo subproceso. Existe la posibilidad de ejecutar cosas en paralelo creando un nuevo proceso hijo para aprovechar la CPU de múltiples núcleos.

Paralelo vs concurrente

De hecho, lo que Promise.allhace es apilar la función de promesas en la cola apropiada (ver arquitectura de bucle de eventos) ejecutarlas simultáneamente (llamar a P1, P2,...) luego esperar cada resultado y luego resolver Promise.all con todas las promesas. resultados. Promise.all fallará con la primera promesa que falle, a menos que usted tenga que gestionar el rechazo usted mismo.

Hay una gran diferencia entre paralelo y concurrente, el primero ejecutará un cálculo diferente en un proceso separado exactamente al mismo tiempo y progresarán a su ritmo, mientras que el otro ejecutará el cálculo diferente uno tras otro sin esperar. el cómputo anterior para terminar y progresar al mismo tiempo sin depender unos de otros.

Finalmente, para responder a su pregunta, Promise.allno se ejecutará ni en paralelo ni de forma secuencial sino de forma concurrente.

Adrien De Peretti avatar Jan 03 '2020 23:01 Adrien De Peretti