Si nos encontramos en una situación donde queremos controlar un grupo de promesas o necesitamos un alto nivel de control al manejar promesas, podemos utilizar el objeto Promise
de Javascript, que incorpora varios métodos estáticos interesantes.
Observa la siguiente tabla:
Métodos | Descripción |
---|---|
Promise.all( list) | Acepta sólo si todas las promesas del |
Promise.allSettled( list) | Acepta sólo si todas las promesas del |
Promise.any( list) | Acepta con el valor de la primera promesa del |
Promise.race( list) | Acepta o rechaza según la primera promesa del |
Métodos estáticos directos | |
Promise.resolve( value) | Devuelve una promesa cumplida directamente con el |
Promise.reject( value) | Devuelve una promesa rechazada directamente con el |
Vamos a ver un ejemplo con cada uno de estos métodos, realizando varias peticiones y descargando varios archivos diferentes que necesitaremos para nuestras tareas.
El método Promise.all()
El método Promise.all()
funciona como un «todo o nada»: le pasas un grupo de varias promesas y el Promise.all()
te devolverá una promesa que se cumplirá cuando todas las promesas del grupo se hayan cumplido. Si alguna de ellas se rechaza, la promesa de Promise.all()
también lo hará.
Observa este ejemplo:
const task1 = fetch("/robots.txt");
const task2 = fetch("/index.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
// Utilizando async/await
const responses = await Promise.all(tasks);
const codes = responses.map(response => response.status); // [200, 200, 200]
const task1 = fetch("/robots.txt");
const task2 = fetch("/index.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
// Utilizando .then()
Promise.all(tasks)
.then(responses => {
const codes = responses.map(response => response.status);
console.log(codes); // [200, 200, 200]
});
- 1️⃣ Realizamos 3
fetch()
, donde cada uno devuelve una promesa. - 2️⃣ Almacenamos esas 3 promesas en un
tasks
. - 3️⃣ Al hacer un
Promise.all(tasks)
devolvemos una nueva promesa. - 4️⃣ Dicha promesa se cumplirá, si todas las que pasamos en el array se cumplen invidiualmente.
- 5️⃣ En el caso de que alguna de las 3 se rechace, la promesa del
Promise.all()
también se rechaza.
Observa en las pestañas, que también se podría realizar utilizando .then()
en lugar de async/await
.
El método Promise.allSettled()
El método Promise.allSettled()
funciona como un «todas procesadas»: devuelve una promesa que se cumple cuando todas las promesas del
const task1 = fetch("/robots.txt");
const task2 = fetch("https://google.com/index.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const results = await Promise.allSettled(tasks); // [{}, {}, {}]
Esta operación nos devuelve un
- La propiedad
status
, donde nos indica si cada promesa individual ha sido cumplida o rechazada - La propiedad
value
, con los valores devueltos por la promesa si se cumple. - La propiedad
reason
, con la razón del rechazo de la promesa si no se cumple.
En este caso, obtendremos que la primera y última promesa se resuelven (fulfilled), mientras que la segunda nos da un error de CORS y se rechaza (rejected).
El método Promise.any()
El método Promise.any()
funciona como «la primera que se cumpla»: Devuelve una promesa con el valor de la primera promesa individual del
const task1 = fetch("/robots.txt");
const task2 = fetch("/index.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const response = await Promise.any(tasks); // Response
Como vemos, en este caso Promise.any()
no devolverá un
El método Promise.race()
El método Promise.race()
funciona como una «la primera que se procese»: la primera promesa del Promise.race()
. Si se cumple, devuelve una promesa cumplida, en caso negativo, devuelve una rechazada.
const task1 = fetch("/robots.txt");
const task2 = fetch("/index.css");
const task3 = fetch("/index.js");
const tasks = [task1, task2, task3];
const response = await Promise.race([task1, task2, task3]);
De forma muy similar a la anterior, Promise.race()
devolverá la promesa que se resuelva primero, ya sea cumpliéndose o rechazándose.
Promesas estáticas
Mediante los métodos estáticos Promise.resolve()
y Promise.reject()
podemos devolver una promesa cumplida o rechazada respectivamente sin necesidad de crear una promesa con new Promise()
, algo que podría ser interesante o cómodo en algunos casos.
Observa que la siguiente función doTask()
no es asíncrona:
const doTask = () => {
const number = 1 + Math.floor(Math.random() * 6);
const isEven = number % 2 === 0;
return isEven ? Promise.resolve(number) : Promise.reject(number);
}
En este caso, generamos un número aleatorio y se devuelve una promesa. Cuando el número generado es par se cumple la promesa, cuando es impar, se rechaza. Sin embargo, ten en cuenta que el problema en este caso es que la promesa no «envuelve» toda la función, por lo que si la tarea tardase algún tiempo en generar el número, no podríamos utilizar el .then()
para consumir la promesa.
Estas funciones estáticas se suelen utilizar en muy pocos casos, para mantener cierta compatibilidad en funciones que se espera que devuelvan una promesa.