What is Promise.race()?
Promise.race() is a static method in JavaScript that takes an iterable of Promises as input and returns a single Promise. This returned Promise settles (either resolves or rejects) as soon as one of the input Promises settles, with the value or reason from that first Promise.
Definition
The Promise.race() method is part of the Promise API and is designed to return a new Promise that is fulfilled or rejected as soon as any of the Promises in the provided iterable are fulfilled or rejected. It's often used when you want to act on the first Promise to complete, regardless of its outcome.
How it Works
- It accepts an iterable (e.g., an Array) containing zero or more Promises.
- It returns a new Promise.
- As soon as the first Promise in the iterable settles (either resolves or rejects), the Promise returned by Promise.race() will settle with the same value or reason.
- Subsequent settlements of other Promises in the iterable are ignored by Promise.race().
- If the iterable is empty, the returned Promise will never settle (it will be pending indefinitely).
- If the iterable contains non-Promise values, they are treated as already-resolved Promises.
Syntax
Promise.race(iterable);
- iterable: An iterable object (like an Array) that contains Promises or other values. Non-Promise values are treated as resolved Promises.
Example
Consider an example where we have multiple Promises with different resolution times. Promise.race() will resolve as soon as the fastest one resolves or rejects.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 1 resolved'), 500);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('Promise 2 rejected'), 200);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 3 resolved'), 800);
});
Promise.race([promise1, promise2, promise3])
.then(value => {
console.log(value); // This will not be reached
})
.catch(error => {
console.log(error); // Output: 'Promise 2 rejected'
});
const promiseA = new Promise((resolve, reject) => {
setTimeout(() => resolve('A is fastest'), 100);
});
const promiseB = new Promise((resolve, reject) => {
setTimeout(() => resolve('B is slower'), 200);
});
Promise.race([promiseA, promiseB])
.then(value => {
console.log(value); // Output: 'A is fastest'
});
In the first scenario, promise2 rejects after 200ms, which is faster than promise1 resolving (500ms) or promise3 resolving (800ms). Therefore, Promise.race() immediately rejects with the reason from promise2. In the second scenario, promiseA resolves fastest, so Promise.race() resolves with its value.
Common Use Cases
- Timeouts: You can race a primary operation with a Promise that rejects after a certain time, effectively implementing a timeout for an asynchronous operation.
- Loading resources: Fetching a resource from multiple CDN servers and using the one that responds first.
- Competition: When you have multiple asynchronous tasks that achieve the same goal, and you only care about the result of the fastest one.
- User interaction: Responding to the first of several possible user interactions (e.g., a click or a keypress).
Comparison with Promise.any()
It's important to distinguish Promise.race() from Promise.any(), which also operates on an iterable of Promises but with a different settling condition.
| Feature | Promise.race() | Promise.any() |
|---|---|---|
| Settlement Condition | Settles as soon as *any* Promise resolves OR rejects. | Settles as soon as *any* Promise resolves. |
| Outcome if first is rejected | The returned Promise rejects with the first rejection reason. | Continues waiting for the next resolved Promise. Only rejects if *all* Promises reject (with an AggregateError). |
| Use Case | Get the result of the *first to finish* (winner, timeout). | Get the result of the *first to succeed* (e.g., multiple resource attempts). |