Cómo usar Promise.all() en JavaScript

Las promesas de JavaScript son una de las formas más populares de escribir funciones asincrónicas que devuelven un único valor al finalizar o fallar la operación.

¿Qué es Promise.all()?

El Promise.all() es un método estático (parte de Promise API) que ejecuta muchas promesas en paralelo y espera hasta que se liquiden todas. Toma una matriz de promesas como entrada (un iterable) y devuelve una sola promesa, que se resuelve cuando todas las promesas en el parámetro iterable se resuelven o cualquiera de ellas se rechaza.

Por ejemplo, suponga que tiene varias promesas para descargar archivos y procesar el contenido una vez que todo esté listo. Ahora tienes dos opciones:

  1. Ejecute estas promesas una por una o conéctelas y procese los datos tan pronto como estén disponibles.
  2. Pásalas todas a Promise.all() como una matriz y ejecutarlos simultáneamente, y procesar los datos una vez que se resuelvan todas las promesas.

¡El segundo enfoque es mejor y más rápido! El Promise.all() devuelve una promesa una vez que todas las promesas se resuelven o cualquiera de ellas se rechaza con un error.

Sintaxis

const promise = Promise.all([Promise1, Promise2, Promise3, ...]);

// run all promises in parallel
promise.then(result => console.log(result))
    .catch(error => console.error(`Error: ${error}`));

Como puede ver, toma una serie de promesas (podría ser iterable) y devuelve una nueva promesa. La nueva promesa se resuelve cuando se liquidan todas las promesas y devuelve una matriz de sus resultados.

Ejemplos

Veamos un ejemplo de Promise.all() :

// A simple promise that resolves after {ts}ms
const wait = (ts) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`Resolved in ${ts}ms`);
        }, ts);
    });
};

// Resolve as a normal promise
wait(1500).then(result => console.log(result)); // Resolved in 1500ms
wait(2000).then(result => console.log(result)); // Resolved in 2000ms
wait(3000).then(result => console.log(result)); // Resolved in 3000ms


// Promise.all
Promise.all([wait(1500), wait(2000), wait(3000)])
    .then(results => console.log(results));
// ["Resolved in 1500ms", "Resolved in 2000ms", "Resolved in 3000ms"]

En el ejemplo anterior, el Promise.all() se asienta después de esperar 3 segundos y devuelve una matriz de resultados que consta de todos los valores devueltos de las promesas.

Otra cosa interesante sobre Promise.all() es que la matriz de salida mantiene el mismo orden que las promesas especificadas en el argumento iterable. Significa que el valor resuelto de la primera promesa se almacenará en el primer elemento de la matriz, la segunda promesa se resolverá en el segundo elemento de la matriz de salida y así sucesivamente.

Si la promesa devuelta por Promise.all() rechaza, se rechaza con el motivo de la primera promesa en la matriz de entrada que rechazó. Pongamos un ejemplo para ver qué sucede si alguna de las promesas es rechazada:

const wait = (ts) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (ts > 2000) {
                reject(`Rejected in ${ts}ms`);
            } else {
                resolve(`Resolved in ${ts}ms`);
            }
        }, ts);
    });
};

// Promise.all
Promise.all([wait(1500), wait(2000), wait(3000)])
    .then(results => console.log(results))
    .catch(error => console.error(`Error while executing: ${error}`));
// Error while executing: Rejected in 3000ms

Como puede ver arriba, si alguna de las promesas falla, el resto de las promesas también fallan. Así Promise.all() inmediatamente rechaza con un error.

Para algunas operaciones, puede que no sea el resultado deseado. Es posible que desee ejecutar todas las promesas incluso si algunas han fallado. Es posible cambiar el comportamiento de rechazo predeterminado manejando el rechazo para cada promesa individual:

// a simple promise that resolves after {ts}ms
const wait = (ts) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (ts > 2000) {
                reject(`Rejected in ${ts}ms`);
            } else {
                resolve(`Resolved in ${ts}ms`);
            }
        }, ts);
    });
};

// Promise.all
Promise.all([
    wait(1500).catch(err => err),
    wait(2000).catch(err => err),
    wait(3000).catch(err => err)
]).then(results => console.log(results));
// ["Resolved in 1500ms", "Resolved in 2000ms", "Rejected in 3000ms"]

Conclusión

Promise.all() ayuda a agregar muchas promesas en una sola promesa y ejecutarlas en paralelo. Devuelve una nueva promesa que se establece una vez que se resuelven todas las promesas en el argumento iterable o se rechaza cualquiera de ellas. Es una de las mejores formas de realizar operaciones asincrónicas simultáneas en JavaScript.

Si tiene alguna pregunta o desea compartir sus comentarios, no dude en enviarme un tweet en cualquier momento.

Codificación feliz 😍