Promise Methods in JavaScript – Handling Multiple Async Operations
Over the past few days, I've learned about asynchronous JavaScript, Promises, async/await, and the Fetch API.
Today, I explored how JavaScript can handle multiple Promises together.
Instead of waiting for asynchronous operations one by one, Promise utility methods allow us to control how multiple operations should be handled.
Today, I focused on:
Promise.all()Promise.allSettled()Promise.race()Promise.any()
Let's dive in.
Why Do We Need Promise Methods?
Imagine an application needs to fetch:
User Data
Posts
Comments
These requests are independent.
Instead of doing:
const users = await getUsers();
const posts = await getPosts();
const comments = await getComments();
we can start them together.
Promise methods help us decide what should happen when multiple asynchronous operations are running.
Promise.all()
Promise.all() waits for all Promises to fulfill.
Example:
const promise1 = Promise.resolve("HTML");
const promise2 = Promise.resolve("CSS");
const promise3 = Promise.resolve("JavaScript");
const result = await Promise.all([
promise1,
promise2,
promise3
]);
console.log(result);
Output:
["HTML", "CSS", "JavaScript"]
The results are returned in the same order as the input Promises.
What Happens If One Promise Fails?
If one Promise rejects, Promise.all() rejects.
const promise1 = Promise.resolve("HTML");
const promise2 = Promise.reject("CSS failed");
const promise3 = Promise.resolve("JavaScript");
Promise.all([
promise1,
promise2,
promise3
])
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
});
The entire Promise.all() operation rejects.
This makes Promise.all() useful when every operation must succeed.
Promise.all() With API Requests
Suppose we need users and posts.
async function getData() {
const [usersResponse, postsResponse] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users"),
fetch("https://jsonplaceholder.typicode.com/posts")
]);
const users = await usersResponse.json();
const posts = await postsResponse.json();
console.log(users);
console.log(posts);
}
getData();
Both requests can be started without waiting for the first one to finish before starting the second.
Promise.allSettled()
Sometimes we don't want one failed Promise to prevent us from seeing the results of the others.
That's where Promise.allSettled() is useful.
const promise1 = Promise.resolve("Success");
const promise2 = Promise.reject("Failed");
const promise3 = Promise.resolve("Completed");
const results = await Promise.allSettled([
promise1,
promise2,
promise3
]);
console.log(results);
The result contains information about every Promise.
For example:
[
{
status: "fulfilled",
value: "Success"
},
{
status: "rejected",
reason: "Failed"
},
{
status: "fulfilled",
value: "Completed"
}
]
When Should We Use Promise.allSettled()?
Use it when every result matters, even if some operations fail.
For example:
Send notification to 5 services
If one service fails, we may still want to know what happened with the other four.
Promise.race()
Promise.race() settles as soon as the first Promise settles.
Example:
const promise1 = new Promise(resolve => {
setTimeout(() => {
resolve("First");
}, 1000);
});
const promise2 = new Promise(resolve => {
setTimeout(() => {
resolve("Second");
}, 2000);
});
const result = await Promise.race([
promise1,
promise2
]);
console.log(result);
Output:
First
The first Promise to settle determines the result.
Important Difference: race() vs any()
This is one of the most important distinctions.
Promise.race() cares about the first Promise to settle.
That means either fulfillment or rejection can win.
Promise.any() cares about the first Promise to fulfill.
Promise.any()
Promise.any() returns the first successfully fulfilled Promise.
const promise1 = Promise.reject("Failed");
const promise2 = new Promise(resolve => {
setTimeout(() => {
resolve("Success!");
}, 1000);
});
const promise3 = new Promise(resolve => {
setTimeout(() => {
resolve("Another success");
}, 2000);
});
const result = await Promise.any([
promise1,
promise2,
promise3
]);
console.log(result);
Output:
Success!
The rejected Promise doesn't win the race.
What If Promise.any() Fails?
If every Promise rejects, Promise.any() rejects with an AggregateError.
Example:
try {
const result = await Promise.any([
Promise.reject("Error 1"),
Promise.reject("Error 2")
]);
console.log(result);
} catch (error) {
console.log(error);
}
All Promises failed, so there was no successful result to return.
Comparing Promise Methods
| Method | Resolves When | Rejects When |
|---|---|---|
Promise.all() |
All fulfill | Any rejects |
Promise.allSettled() |
All settle | It doesn't reject because of member Promise rejection |
Promise.race() |
First Promise settles | First Promise rejects |
Promise.any() |
First Promise fulfills | All reject |
This table is something I want to remember because each method solves a different problem.
Visualizing the Difference
Promise.all()
→ Wait for everyone
→ One failure = rejection
Promise.allSettled()
→ Wait for everyone
→ Give me every result
Promise.race()
→ Give me whoever settles first
Promise.any()
→ Give me whoever succeeds first
Practical Example
Imagine three servers can provide the same data.
const servers = [
fetch("https://server-one.example/data"),
fetch("https://server-two.example/data"),
fetch("https://server-three.example/data")
];
If we want the first successful server, Promise.any() may be appropriate.
If we want all servers to respond successfully, Promise.all() may be appropriate.
If we want to know how every server performed, Promise.allSettled() may be appropriate.
Choosing the correct Promise method depends on what the application actually needs.
Best Practices
✔ Use Promise.all() when all operations need to succeed.
✔ Use Promise.allSettled() when you need the result of every operation regardless of failures.
✔ Use Promise.race() when the first settled result should determine the outcome.
✔ Use Promise.any() when the first successful result is what matters.
✔ Use parallel execution for independent asynchronous operations when appropriate.
✔ Still handle errors when working with Promise utilities.
My Biggest Takeaway
Today, I learned that Promises aren't just about handling one asynchronous operation.
JavaScript provides several powerful tools for coordinating multiple asynchronous operations.
The biggest distinction I learned is:
Promise.all() → Everyone must succeed
Promise.allSettled() → Tell me what happened to everyone
Promise.race() → First settled result wins
Promise.any() → First successful result wins
Understanding these methods will become extremely useful when I start building applications that make multiple API requests at the same time.
