Practice Promise.all and Promise.race
Asynchronous Processing in JavaScript
Asynchronous processing is a cornerstone of JavaScript, enabling efficient handling of tasks that cannot be completed synchronously. Two key constructs, Promise.all() and Promise.race(), are essential for managing multiple asynchronous operations. This article explores their usage, differences, and practical applications.
Promise.all()
Promise.all() resolves to an array of values when all specified promises resolve, or rejects immediately if any promise fails. It is ideal for scenarios where multiple asynchronous tasks need to be executed concurrently.
Usage Example
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3])
.then(values => {
console.log(values); // [1, 2, 3]
})
.catch(error => {
console.error("One or more promises failed:", error);
});
Key Features
- Concurrent Execution: All promises are processed simultaneously.
- Error Handling: If any promise fails, the entire
Promise.all()rejects. - Array Aggregation: Results are collected into an array.
Use Cases
- Parallel API calls to reduce latency.
- Batch processing of multiple tasks.
Promise.race()
Promise.race() resolves based on the first promise to resolve or reject. It is useful for checking the status of multiple asynchronous operations quickly.
Usage Example
const promise1 = Promise.resolve("Result from Promise 1");
const promise2 = Promise.reject("Error from Promise 2");
Promise.race([promise1, promise2])
.then(result => {
console.log(result); // "Result from Promise 1"
})
.catch(error => {
console.error(error); // "Error from Promise 2"
});
Key Features
- First to Resolve/Reject: The first promise in the array determines the outcome.
- Simplified Logic: Requires fewer lines of code compared to
Promise.all().
Use Cases
- Quick checks for the status of multiple requests.
- Handling timeouts or early termination of long-running tasks.
Differences and When to Use
| Feature | Promise.all() | Promise.race() |
|---|---|---|
| Resolution | Resolves only if all promises resolve | Resolves based on the first promise |
| Error Handling | Rejects if any promise fails | Rejects if the first promise fails |
| Performance | Efficient for large numbers of promises | Efficient for checking early outcomes |
| Use Case | Parallel processing of multiple tasks | Quick status checks for multiple tasks |
When to Choose Each
- Use
Promise.all()when all promises must succeed, such as processing a batch of data. - Use
Promise.race()when you need to know the status of multiple tasks quickly, like checking if a user is logged in.
Practical Examples
Scenario 1: Parallel API Calls
const api1 = fetch("https://api.example.com/data1");
const api2 = fetch("https://api.example.com/data2");
Promise.all([api1, api2])
.then(response => {
console.log("All requests completed:", response);
})
.catch(error => {
console.error("One or both requests failed:", error);
});
Scenario 2: Early Termination
const timeout = setTimeout(() => {
console.log("Timeout triggered");
}, 1000);
Promise.race([fetchData(), timeout])
.then(data => {
console.log("Data received:", data);
})
.catch(error => {
console.error("Request failed:", error);
});
Conclusion
Promise.all() and Promise.race() are critical tools for managing asynchronous operations in JavaScript. While Promise.all() ensures all promises succeed, Promise.race() provides efficient, early feedback. Understanding their differences and use cases allows developers to build robust, responsive applications. By leveraging these constructs, asynchronous processing becomes both scalable and manageable.