JavaScript Promise.any()
Method: Resolving When Any Promise Succeeds
The Promise.any()
method in JavaScript is a powerful tool for handling multiple asynchronous operations. It takes an iterable of promises and resolves as soon as any one of the promises fulfills. If all promises reject, it rejects with an AggregateError
containing all the rejection reasons. This is particularly useful when you have multiple sources for the same data and want to use the first one that responds successfully.
Purpose and Use Cases
The primary purpose of Promise.any()
is to race multiple promises against each other, resolving with the first success. Common use cases include:
- Redundant Requests: Querying multiple servers for the same resource and using the fastest response.
- Fallback Strategies: Trying multiple methods to achieve a goal and using the first successful outcome.
- Parallel Execution: Running multiple independent tasks and proceeding as soon as one completes.
Syntax
Promise.any(iterable);
Parameters
iterable
: An iterable object (e.g., Array, Set) containing promises.
Return Value
- A
Promise
that resolves with the value of the first fulfilled promise in the iterable. - If all promises reject, the returned
Promise
rejects with anAggregateError
.
Examples
Basic Example: Resolving with the First Fulfilled Promise
In this example, Promise.any()
resolves with the value of the first promise that fulfills.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => reject("Promise 1 Rejected"), 500);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve("Promise 2 Resolved"), 300);
});
const promise3 = new Promise((resolve) => {
setTimeout(() => resolve("Promise 3 Resolved"), 400);
});
Promise.any([promise1, promise2, promise3])
.then((value) => {
console.log("Resolved:", value);
})
.catch((error) => {
console.error("Rejected with:", error);
});
Output:
Resolved: Promise 2 Resolved
In this case, promise2
resolves first, so Promise.any()
resolves with its value.
Handling Rejections: AggregateError
If all promises reject, Promise.any()
rejects with an AggregateError
.
const promise4 = new Promise((resolve, reject) => {
setTimeout(() => reject("Promise 4 Rejected"), 300);
});
const promise5 = new Promise((resolve, reject) => {
setTimeout(() => reject("Promise 5 Rejected"), 200);
});
Promise.any([promise4, promise5])
.then((value) => {
console.log("Resolved:", value);
})
.catch((error) => {
console.error("Rejected with:", error.errors);
});
Output:
Rejected with: [ 'Promise 5 Rejected', 'Promise 4 Rejected' ]
Here, both promise4
and promise5
reject, resulting in an AggregateError
containing the rejection reasons.
Using with Asynchronous Functions
Promise.any()
works seamlessly with asynchronous functions.
async function asyncFunc1() {
await new Promise((resolve) => setTimeout(resolve, 400));
return "Async Func 1 Resolved";
}
async function asyncFunc2() {
await new Promise((resolve) => setTimeout(resolve, 200));
return "Async Func 2 Resolved";
}
Promise.any([asyncFunc1(), asyncFunc2()])
.then((value) => {
console.log("Resolved:", value);
})
.catch((error) => {
console.error("Rejected with:", error);
});
Output:
Resolved: Async Func 2 Resolved
asyncFunc2
resolves faster, so Promise.any()
resolves with its return value.
Real-World Example: Fetching Data from Multiple APIs
Consider a scenario where you want to fetch data from multiple APIs and use the response from the first API that responds successfully.
const api1Url = "https://rickandmortyapi.com/api/character";
const api2Url = "https://api.publicapis.org/random";
const fetchFromAPI1 = () =>
fetch(api1Url).then((response) => {
if (!response.ok) {
throw new Error(`API 1 Failed: ${response.status}`);
}
return response.json();
});
const fetchFromAPI2 = () =>
fetch(api2Url).then((response) => {
if (!response.ok) {
throw new Error(`API 2 Failed: ${response.status}`);
}
return response.json();
});
Promise.any([fetchFromAPI1(), fetchFromAPI2()])
.then((data) => {
console.log("Data fetched successfully:", data);
})
.catch((error) => {
console.error("Failed to fetch data from any API:", error);
});
This example attempts to fetch data from two different APIs. Promise.any()
resolves with the data from the first API that responds successfully. If both APIs fail, it catches the AggregateError
.
Tips and Considerations
- Error Handling: Always include a
.catch()
block to handle the case where all promises reject. - Performance:
Promise.any()
can improve performance by utilizing the fastest successful response from multiple sources. - Browser Compatibility: Ensure that you are using a modern browser that supports
Promise.any()
. If not, consider using polyfills. âšī¸
Browser Support
The Promise.any()
method is supported in modern browsers. However, for older browsers, you might need to use a polyfill to ensure compatibility. đģ
| Browser | Version | Support |
| ————– | ——- | ——- |
| Chrome | 85 | Yes |
| Firefox | 79 | Yes |
| Safari | 14 | Yes |
| Edge | 85 | Yes |
| Opera | 71 | Yes |
| Node.js | 15 | Yes |
Conclusion
The Promise.any()
method is a valuable addition to JavaScript’s asynchronous programming toolkit. It simplifies the process of racing multiple promises and resolving with the first success, making it ideal for scenarios where redundancy and fallback strategies are crucial. By understanding how to use Promise.any()
, you can write more efficient and robust asynchronous code. đ