Me gustaría aclarar este punto, ya que la documentación no es demasiado clara al respecto;
P1: ¿Está Promise.all(iterable) procesando todas las promesas secuencialmente o en paralelo? O, más específicamente, ¿es el equivalente de 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 los p1 , p2 , p3 , p4 , p5 , etc. se llaman al mismo tiempo (en paralelo) y los resultados se devuelven tan pronto como todos se resuelven (o uno rechaza)?
P2: Si Promise.all se ejecuta en paralelo, ¿hay alguna forma conveniente de ejecutar un iterable secuencialmente?
Nota : no quiero usar Q o Bluebird, sino todas las especificaciones nativas de ES6.
¿Está
Promise.all(iterable)ejecutando todas las promesas?
No, las promesas no pueden "ser ejecutadas". Comienzan su tarea cuando se están creando (solo representan los resultados) y está ejecutando todo en paralelo incluso antes de pasarlos a Promise.all .
Promise.all solo espera múltiples promesas. No importa en qué orden se resuelven o si los cálculos se ejecutan en paralelo.
¿Hay alguna manera conveniente de ejecutar un iterable secuencialmente?
Si ya tiene sus promesas, no puede hacer mucho más que Promise.all([p1, p2, p3, …]) (que no tiene una noción de secuencia). Pero si tiene una iteración de funciones asincrónicas, puede ejecutarlas secuencialmente. Básicamente necesitas obtener de
[fn1, fn2, fn3, …]para
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()) 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ápido" . Use Promise.allSettled para completar todas las iteraciones en paralelo, incluso si algunas fallan.
for (const item of items) { await fetchItem(item) }Ventajas: Cada iteración puede compartir las variables en el ciclo. Se comporta como un código síncrono imperativo normal.
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 mediante la creación de un nuevo proceso secundario para aprovechar la CPU de múltiples núcleos.
De hecho, lo que hace Promise.all es apilar la función de promesas en la cola apropiada (consulte la arquitectura de bucle de eventos) ejecutándolas simultáneamente (llame a P1, P2,...) luego esperando cada resultado y luego resolviendo Promise.all con todos los resultados de las promesas. Promise.all fallará en la primera promesa que falle a menos que tenga que manejar el rechazo usted mismo.
Hay una gran diferencia entre paralelo y concurrente, el primero ejecutará un cómputo diferente en un proceso separado exactamente al mismo tiempo y progresarán a su ritmo, mientras que el otro ejecutará el cómputo diferente uno tras otro sin esperar a que el cómputo anterior para terminar y avanzar al mismo tiempo sin depender unos de otros.
Finalmente, para responder a su pregunta, Promise.all no se ejecutará en paralelo ni secuencialmente sino simultáneamente.