JavaScript
Promise.all
Asynchronous Programming
Promises
Coding Techniques

Perform actions as promises get fulfilled using Promise.all

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Understanding Promise.all() in JavaScript

JavaScript provides several utilities for handling asynchronous operations, and one such powerful tool is the Promise object. When you have multiple promises that need to be executed concurrently and collective success or failure of these promises dictates the next set of actions, Promise.all() becomes highly useful. This article delves into how Promise.all() can be used to perform actions as promises get fulfilled.

What is Promise.all()?

Promise.all() is a method provided by JavaScript's Promise class that takes an iterable (e.g., an array) of promises and returns a single promise that resolves when all of the promises in the array have resolved or when one of them rejects.

Key attributes of Promise.all():

  • Resolved: The resulting promise is resolved when all input promises are resolved. The resolved values are returned as an array in the order in which promises were passed.
  • Rejected: It gets rejected as soon as one of the promises gets rejected. The reason for the rejection is the same as the first promise that rejects.

Syntax

javascript
Promise.all(iterable);
  • iterable: An iterable object (e.g., an array) containing promises.

Examples of Using Promise.all()

Let's consider a scenario where you have multiple asynchronous tasks (simulated by promises) fetching data from different APIs. You want to perform operations once all the data is fetched successfully.

javascript
1const fetchData1 = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Data from API 1"), 1000);
3});
4
5const fetchData2 = new Promise((resolve, reject) => {
6    setTimeout(() => resolve("Data from API 2"), 1500);
7});
8
9const fetchData3 = new Promise((resolve, reject) => {
10    setTimeout(() => resolve("Data from API 3"), 2000);
11});
12
13Promise.all([fetchData1, fetchData2, fetchData3])
14    .then((results) => {
15        console.log("All data fetched:");
16        results.forEach((data) => console.log(data));
17    })
18    .catch((error) => {
19        console.error("An error occurred:", error);
20    });

In this example, fetchData1, fetchData2, and fetchData3 are asynchronous operations that resolve after different durations. Promise.all() waits for all three to resolve, and then the aggregated results are processed in the then() clause. If any of the promises were to reject, the catch() block would handle the error.

Advanced Use Cases

  1. Batch Processing: Often used to batch multiple network requests or I/O operations and wait for their completion.
  2. Parallel Execution: Leverages concurrent execution of asynchronous functions to improve performance in applications such as fetching multiple resources from a server.
  3. Graceful Degradation: Can be used in creating APIs or SDK tools where a single point of failure should halt operations to prevent further inconsistencies.
  4. Aggregate Multiple Resources: Used often when multiple services send back partial data needed to compile a complete dataset.

Table: Key Characteristics of Promise.all()

FeatureDescription
InputAn iterable (e.g., array) of promise objects
Resolved ConditionWhen all promises in the array have resolved, returning values in order
Rejected ConditionWhen any single promise in the array rejects (does not wait for others)
Use CasesBatch processing, parallel execution, aggregation of multiple resources

Failure Handling in Promise.all()

Because Promise.all() short-circuits on the first rejection, it is important to manage failures carefully. Consider the following approval pipeline:

  • Wrap with Try-Catch: Often used to capture any errors at the promise level.
javascript
1async function processData() {
2    try {
3        const [api1Result, api2Result] = await Promise.all([
4            fetchDataFromAPI1(),
5            fetchDataFromAPI2()
6        ]);
7        console.log("Data:", api1Result, api2Result);
8    } catch (error) {
9        console.error("Error fetching data:", error);
10    }
11}
  • Custom Fallback: Use .catch() for individual promises before passing them to Promise.all().

Handling Complex Logic

When multiple sets of promises need to be resolved one after another, nesting Promise.all() calls or combining with Promise.allSettled() helps extend functionality by handling fulfilled and rejected promises differently.

Final Thoughts

Promise.all() is indispensable for executing concurrent asynchronous operations efficiently in JavaScript. Always ensure error handling is robust since Promise.all() short-circuits on the first rejected promise. Understanding its behavior provides a solid foundation for advanced asynchronous programming, ensuring your applications are performant and reliable.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.