JavaScript is a versatile and powerful programming language used for building dynamic web applications. One of its key features is asynchronous programming, which allows us to perform tasks concurrently without blocking the main execution thread. Let’s explore a fundamental method for managing asynchronous operations in JavaScript called Promise.race()
. We’ll break it down into easy-to-understand concepts to use it effectively in our code.
What is a Promise?
Before diving into Promise.race()
, it’s important to understand what a Promise is. A Promise is an object that represents a value that may not be available yet but will be in the future. It can be in one of three states:
- Pending: The initial state, representing that the operation is still in progress.
- Fulfilled: The operation has been completed successfully, and the Promise now holds a resolved value.
- Rejected: The operation has failed, and the Promise holds a reason for the failure.
Promises are widely used for managing asynchronous operations like fetching data from a server, reading files, or handling timeouts.
The Need for Promise.race()
In many scenarios, we may have multiple asynchronous operations and want to respond as soon as the first one completes, regardless of whether it succeeded or failed. This is where Promise.race()
it comes into play. Promise.race()
allows us to compete multiple Promises against each other and return the result of the first Promise that is resolved or rejected.

If all goes right, whichever promise finishes first(resolves) wins but if any one of the promises is rejected during the race, the race is terminated(rejected) at that instant.
Basic Syntax
Here’s the basic syntax of Promise.race()

iterable
: Usually an array of Promises to race against each other.
How Promise.race()
Works
Imagine we have several Promises representing different tasks and want to know which one finishes first. We can use Promise.race()
to achieve this:
![const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 500);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Promise 3 rejected');
}, 1500);
});
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log('First Promise to Resolve/Reject:', result);
})
.catch((error) => {
console.error('First Promise to Resolve/Reject:', error);
});](https://mariyabaig.com/wp-content/uploads/2023/10/carbon-12-1024x919.png)
In the above example, Promise.race()
takes an array of Promises as its argument. It will return a new Promise that resolves or rejects as soon as the first Promise in the array resolves or rejects.
In our case, promise2
resolves the fastest, so the .then()
block is executed, logging “Promise 2 resolved.”
The other Promises continue running in the background, but their results are ignored because we only care about the first one to finish.
Use Cases
Now let’s look at some practical use cases for Promise.race()
:
1. Timeout Handling
We can use Promise.race()
to implement a timeout mechanism for asynchronous operations. For example, if we’re fetching data from a server, we can set a timeout to cancel the request if it takes too long:
![const fetchWithTimeout = (url, timeout) => {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject('Request timed out');
}, timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
};
fetchWithTimeout('https://api.example.com/data', 5000)
.then((data) => {
console.log('Data:', data);
})
.catch((error) => {
console.error('Error:', error);
});](https://mariyabaig.com/wp-content/uploads/2023/10/carbon-10-928x1024.png)
In this example, fetchWithTimeout
returns a Promise that races between the actual fetch request and a timeout Promise.
If the fetch request takes longer than the specified timeout (5 seconds in this case), the timeout Promise will be rejected, and we can handle it accordingly.
2. Race for the Fastest Response
Suppose we have multiple endpoints from which we can fetch data, and we want to get the response from the fastest server:
![const server1 = fetch('https://api.server1.com/data')
const server2 = fetch('https://api.server2.com/data')
const server3 = fetch('https://api.server3.com/data')
Promise.race([server1, server2, server3])
.then((response) => {
console.log('Fastest Response:', response.url);
})
.catch((error) => {
console.error('Error:', error);
});](https://mariyabaig.com/wp-content/uploads/2023/10/carbon-11-1024x589.png)
Here we’re fetching data from multiple servers concurrently. The Promise.race()
method will resolve with the response of the server that responds the quickest, allowing us to process the data from that server first.
3. Handling Errors with promise.race
It’s important to note that while Promise.race()
is great for handling the fastest completion of Promises, it won’t catch errors in the other Promises that are still running.
In the earlier examples, if promise3
in the first code snippet encounters an error, it won’t be caught by the .catch()
block because Promise.race()
only considers the first resolved or rejected Promise.
To handle errors in all Promises simultaneously, we can wrap them in a Promise.all()
and handle errors collectively.
Promise.race : Conclusion
Promise.race()
is a powerful tool in our JavaScript asynchronous toolkit. It allows us to efficiently handle scenarios where we want the first asynchronous operation to resolve or reject among multiple competing operations. Whether it’s implementing timeouts or fetching data from the fastest server, understanding Promise.race()
is essential for writing responsive and efficient asynchronous code in JavaScript.