Introduction to Promise.race()
In JavaScript, the Promise.race()
method returns a promise with the outcome of the first promise that either fulfils or rejects, with the value or reason from said promise. Promise.race
 solves interesting problems. Suppose that you’re implementing a web frontend with a highly available API backend or distributed caches—a common occurrence in modern cloud deployments. You have an API backend in the US East region and one in the US West region. You can use Promise.race
 to fetch data from both regions at the same time. The region with the lowest latency wins. This situation could guarantee consistent performance of your backend as your users roam about the country.
In this article, we will discuss how to use the promise.race
method in JavaScript.
Using Promise.race
method
Here is an example of how Promise.race()
can be used:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("First promise resolved");
}, 500);
});
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("First promise rejected");
}, 1000);
});
Promise.race([promise1, promise2])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
Output
First promise resolved
In this example, promise1
will resolve after 500 milliseconds, and promise2
will reject after 1000 milliseconds. Since promise1
is the first to resolve or reject, the Promise.race()
promise will be resolved with the value 'First promise resolved'
, and the then()
handler will be executed. If promise2
had been the first to resolve or reject, the Promise.race()
promise would have been rejected with the value 'First promise rejected'
, and the catch()
handler would have been executed.
Here is another example of how Promise.race()
can be used:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("First promise resolved");
}, 1000);
});
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("First promise rejected");
}, 500);
});
let timeout = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Promise timed out");
}, 750);
});
Promise.race([promise1, promise2, timeout])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
Output
First promise rejected
In this example, promise1
will resolve after 1000 milliseconds, promise2
will reject after 500 milliseconds, and the timeout promise will reject after 750 milliseconds. Since the timeout promise is the first to reject, the Promise.race()
promise will be rejected with the value First promise rejected
, and the catch()
handler will be executed. If either promise1
or promise2
had been the first to resolve or reject, the Promise.race()
promise would have been resolved or rejected with the value from that promise, and the then()
handler would have been executed.
Promise.all()
and Promise.race()
The static helpers Promise.all([ .. ])
 and Promise.race([ .. ])
 on the ES6 Promise API both create a Promise as their return value. The resolution of that promise is controlled entirely by the array of promises that you pass in.
For Promise.all([ .. ])
, all the promises you pass in must fulfill for the returned promise to fulfill. If any promise is rejected, the main returned promise is immediately rejected, too (discarding the results of any of the other promises). For fulfillment, you receive an array of all the passed in promises’ fulfillment values. For rejection, you receive just the first promise rejection reason value. This pattern is classically called a gate: all must arrive before the gate opens.
For Promise.race([ .. ])
, only the first promise to resolve (fulfillment or rejection) wins, and whatever that resolution is becomes the resolution of the returned promise. This pattern is classically called a latch: the first one to open the latch gets through. Consider:
var p1 = Promise.resolve( 42 );
var p2 = Promise.resolve( "Hello World" );
var p3 = Promise.reject( "Oops" );
Promise.race( [p1,p2,p3] )
.then( function(msg){
console.log( msg ); // 42
} );
Promise.all( [p1,p2,p3] )
.catch( function(err){
console.error( err ); // "Oops"
} );
Promise.all( [p1,p2] )
.then( function(msgs){
console.log( msgs ); // [42,"Hello World"]
} );
Be careful! If an empty array is passed to Promise.all([ .. ])
, it will fulfill immediately, but Promise.race([ .. ])
 will hang forever and never resolve.
Summary
The Promise.race()
method allows you to create a new promise that is resolved or rejected when the first promise in a provided iterable (such as an array) of promises is resolved or rejected. This can be useful for implementing timeouts for promises or for canceling promises when a specific event occurs.
References
Promise.race() - JavaScript | MDN (mozilla.org)