En el artículo anterior, vimos los problemas que podemos experimentar cuando trabajamos con múltiples promesas y necesitamos esperar a tener los resultados.
El problema de map()
con async
/await
Una de las opciones que podemos escoger sería utilizar async
/await
para resolver el grupo de promesas que tenemos almacenado en un array y que recorremos con un .map()
para generar un nuevo array de resultados:
const task1 = fetch("/robots.txt"); // fetch devuelve una promise
const task2 = fetch("/theme.css"); // fetch devuelve una promise
const task3 = fetch("/index.js"); // fetch devuelve una promise
const tasks = [task1, task2, task3]; // Array de promises
// Recorrer el array de promesas para resolverlas con await
// y obtener un array derivado (map) con los datos resueltos
const responses = tasks.map(async (promise) => {
return await promise
});
responses // [Promise, Promise, Promise]
Aunque el planteamiento es correcto y no nos dará error, este código no funciona porque await
sólo se puede utilizar dentro de una función async
y los .map()
son síncronos y no esperan a que se resuelvan las promesas.
Alternativa 1: Usar un bucle for
Una alternativa posible es usar un bucle for
para iterar sobre el array de promesas, resolverlas con await
, y generar un nuevo array con los resultados resueltos:
const task1 = fetch("/robots.txt");
const task2 = fetch("/theme.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const responses = [];
for (let i = 0; i < tasks.length; i++) {
const promise = tasks[i];
responses[i] = await promise;
}
responses // [Response, Response, Response]
Como puedes ver, en este caso no tendríamos problema. SIn embargo, el código es difícil de leer.
Alternativa 2: Usar un bucle for...of
De forma muy similar a la anterior, podemos utilizar un bucle for...of
:
const task1 = fetch("/robots.txt");
const task2 = fetch("/theme.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const responses = [];
for (const promise of tasks) {
responses.push(await promise);
}
responses // [Response, Response, Response]
En este caso, la sintaxis es un poco más elegante y legible.
Alternative 3: Usar Promise.all()
Javascript tiene varios métodos estáticos en Promise
para manejar promesas en grupo. Promise.all()
es uno de los más comunes:
const task1 = fetch("/robots.txt");
const task2 = fetch("/theme.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const responses = await Promise.all(tasks);
responses // [Response, Response, Response]
Como puedes ver, la sintaxis es muy sencilla y nos permite esperar a que se resuelvan todas las promesas del array tasks
. Una vez resueltas, las respuestas se almacenan en un nuevo array, que hemos llamado responses
.
En el siguiente artículo aprenderemos a utilizar tanto
Promise.all()
en profundidad, como otros métodos para manejar promesas en grupo.