ECMAScript 2021 is the latest JavaScript version that introduced multiple new features to the JavaScript language.
In this blog, we will cover Promise.any() method that was a part of ECMAScript 2021 addition.
Promise.any() method accepts a list of Promise objects as an iterable object and, as soon as one of the promises from the list fulfills, it returns a single promise that resolves with the value from that promise.
If no promise in the iterable is fulfilled, then the returned promise is rejected with an AggregateError, which is a new subclass of the Error.
Let’s take an example to understand it better.
const promise1 = fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(
(response) => response.json()
);
const promise2 = fetch("https://jsonplaceholder.typicode.com/todos/2")
.then(
(response) => response.json()
);
const promise3 = fetch("https://jsonplaceholder.typicode.com/todos/3")
.then(
(response) => response.json()
);
Promise.any([promise1, promise2, promise3])
.then((value) =>console.log(value))
.catch((error) => console.log(error))
//Output
{
completed: false,
id: 1,
title: "delectus aut autem",
userId: 1
}
In the above example, we are passing three different promises to Promise.any() method for fetching a todo item using a fake API.
promise1 is the first promise to be fulfilled so its value (a todo object) is returned from the Promise.any() method and printed to the console.
Syntax:
Promise.any(iterable);
Return value:
- An already rejected Promise, if the iterable passed, is empty.
Promise.any([]);
//Output
Promise {<rejected>: AggregateError: All promises were rejected}
- An asynchronously resolved Promise, if the iterable passed, contains no promises.
Promise.any([100,200,300]);
//Output
Promise {<fulfilled>: 100}
- First resolved value, if any of the promises in the given iterable resolves.
const promiseError = new Promise((resolve, reject) => {
reject("Error coming!");
});
const promiseSlow = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "Slow as a tortoise");
});
const promiseFast = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "Fast as a bullet");
});
Promise.any([promiseError, promiseSlow, promiseFast])
.then((value) => {
console.log(value);
});
//Output "Fast as a bullet"
- Error if all the promises are rejected.
const pErr1 = new Promise((resolve, reject) => {
reject("Always fails");
});
const pErr2 = new Promise((resolve, reject) => {
reject("I will also fail");
});
Promise.any([pErr1, pErr2]).catch((err) => {
console.log(err);
});
//Output
AggregateError: All promises were rejected
Promise {<fulfilled>: undefined}
Promise.race vs Promise.any
Promise.race() returns the first settled value (either fulfillment or rejection) from a list of promises while the Promise.any() returns the first fulfilled value.
Let’s take an example to understand it better.
const promise1 = fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(
(response) => response.json()
);
const promise2 = new Promise((resolve, reject) => {
reject("I am a rejected value");
});
Promise.race([promise1, promise2])
.then((value) => console.log(value))
.catch((value) => console.log(value));
//Output "I am a rejected value"
Promise.any([promise1, promise2])
.then((value) => console.log(value))
.catch((value) => console.log(value));
//Output
{
completed: false,
id: 1,
title: "delectus aut autem",
userId: 1
}
In the above example, promise1 will fetch a todo item from an endpoint but, promise2 will be instantly rejected.
As we know, Promise.race() returns the first promise that is either resolved or rejected from a list of promises, so the value of promise2 is returned as it is instantly rejected.
But, in the case of Promise.any(), the first resolved value is returned, so we get a todo object as an output.