How to Handle an Array of Promises in JavaScript

How to Handle an Array of Promises in JavaScript

When working with asynchronous code in JavaScript, you often need to run multiple promises at the same time.

For example:

  • Fetching data from multiple API endpoints
  • Uploading several files simultaneously
  • Running multiple database queries
  • Processing multiple asynchronous tasks in parallel

Handling these operations one by one can make your application slower and harder to manage.

Instead, JavaScript provides powerful built-in methods to efficiently manage arrays of promises, allowing multiple asynchronous operations to run in parallel and be handled in a clean, structured way.

In this blog, we’ll explore how to work with multiple promises step by step.

Before diving deeper, make sure you understand the basics of Promises.


🔹 The Problem: Multiple Async Tasks

Imagine you need to fetch data from 3 APIs:

await fetchUser();
await fetchPosts();
await fetchComments();

If you wait for each one sequentially, it becomes slow.

We need them to run in parallel.


🔹 Creating an Array of Promises

Example:

const promise1 = Promise.resolve("User");
const promise2 = Promise.resolve("Posts");
const promise3 = Promise.resolve("Comments");

const promises = [promise1, promise2, promise3];

Now we have an array of promises.

But how do we handle them together?


1️⃣ Promise.all()

This is the most common method.

Waits for ALL promises to succeed.
If ONE fails → everything fails.
Promise.all(promises)
  .then(results => {
    console.log(results);
  })
  .catch(error => {
    console.error(error);
  });
Output: User, Posts, Comments

What If One Promise Fails?

const promise2 = Promise.reject("Failed!");

Then Promise.all() immediately fails.

That’s sometimes dangerous.


2️⃣ Promise.allSettled()

This method waits for ALL promises, whether they succeed or fail.

It never rejects.

Promise.allSettled(promises)
  .then(results => console.log(results));

It returns:

[
  { status: "fulfilled", value: "User" },
  { status: "rejected", reason: "Error" }
]

3️⃣ Promise.race()

Returns the FIRST promise that settles (success OR failure).
Promise.race(promises)
  .then(result => console.log(result));

Useful for:

  • Timeouts
  • Fastest response

4️⃣ Promise.any()

Returns the first SUCCESSFUL promise.

If all fail → throws error.


🔹 Parallel vs Sequential Execution

❌ Sequential (Slow)

await fetchUser();
await fetchPosts();
await fetchComments();

Each waits for the previous.


✅ Parallel (Fast)

await Promise.all([
  fetchUser(),
  fetchPosts(),
  fetchComments()
]);

All run at the same time.

Much faster.


🔹 Real-World Example

Imagine loading a dashboard:

  • User data
  • Notifications
  • Messages
  • Settings

Instead of:

Wait → Wait → Wait → Wait

You do:

Load everything together

That’s why Promise.all() is powerful.


🔹 Common Mistakes

❌ Forgetting to return promises inside map
❌ Using sequential await unnecessarily
❌ Not handling rejected promises
❌ Not understanding that Promise.all fails fast


🔹 Performance Tip

When using arrays:

const results = await Promise.all(
  urls.map(url => fetch(url))
);

This runs all fetches concurrently.

Professional pattern.


🔹 Quick Comparison Table

MethodFails Fast?Waits All?Returns First?
Promise.all✅ Yes❌ No❌ No
Promise.allSettled❌ No✅ Yes❌ No
Promise.raceDepends❌ No✅ Yes
Promise.any❌ Only if all fail❌ No✅ First success

🔹 Conclusion

When working with multiple async tasks:

  • Use Promise.all() for parallel success
  • Use Promise.allSettled() when you need all results
  • Use Promise.race() for fastest result
  • Use Promise.any() for first success