HANDLING MULTIPLE PROMISES IN JAVASCRIPT
Sometimes you need to work with many promises at the same time.
This note explains how to handle multiple promises in simple language.
You will learn:
- why group promise methods are needed
- how
Promise.all()works - how
Promise.allSettled()works - how
Promise.race()works - when to use each one
- common beginner mistakes
1. Why do we need methods for multiple promises?
Sometimes one promise is not enough.
For example, you may need to:
- load users
- load posts
- load comments
All at the same time.
Or maybe you only care about the fastest result.
JavaScript has special methods for this.
Diagram 1. One promise vs many promises
One async task
-> one promise
Many async tasks
-> many promises
-> need a way to manage them together
This is why methods like Promise.all(), Promise.allSettled(), and Promise.race() exist.
2. Promise.all()
Promise.all() is used when you want to wait for all promises to succeed.
Syntax
Promise.all([promise1, promise2, promise3])
It takes an array of promises and returns one new promise.
Diagram 2. Main idea of Promise.all()
Promise.all([...])
-> wait for all promises
if all succeed
-> one fulfilled promise with array of results
if one fails
-> one rejected promise with that error
3. Example: all promises succeed
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(values => console.log(values))
.catch(error => console.log(error));
Output
[1, 2, 3]
All 3 promises were fulfilled.
So Promise.all() also becomes fulfilled.
Its result is an array of values.
Diagram 3. Promise.all() success flow
p1 -> fulfilled -> 1
p2 -> fulfilled -> 2
p3 -> fulfilled -> 3
-> Promise.all(...)
-> fulfilled with [1, 2, 3]
4. Important rule: result order
The result array keeps the same order as the promises in the input array.
It does not depend on which promise finishes first.
Example idea
Input order:
[p1, p2, p3]
Result order:
[value of p1, value of p2, value of p3]
Diagram 4. Order rule
Input:
[p1, p2, p3]
Even if p3 finishes first,
the result still stays:
[result of p1, result of p2, result of p3]
This is very important. Promise.all() preserves input order.
5. Example: one promise fails
const p1 = Promise.resolve(1);
const p2 = Promise.reject("Rejected promise 2");
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(values => console.log(values))
.catch(error => console.log(error));
Output
"Rejected promise 2"
As soon as one promise is rejected, Promise.all() becomes rejected too.
So then() does not run. catch() runs instead.
Diagram 5. Promise.all() failure flow
p1 -> fulfilled
p2 -> rejected
p3 -> fulfilled
-> Promise.all(...)
-> rejected with error from p2
6. Does Promise.all() wait after a rejection?
Easy answer: Promise.all() does not wait for a final success result after one rejection.
It rejects as soon as the first rejection happens.
But also important: the other promises may still continue running in the background, because JavaScript usually cannot magically stop them.
Promise.all() settles early,
but other original promises may still continue.
Diagram 6. Rejection in Promise.all()
p1 still running
p2 rejects
p3 still running
-> Promise.all(...) rejects immediately
-> result is already decided
Clean beginner rule:
Promise.all() = all must succeed
one rejection = whole result fails
7. When to use Promise.all()
Use Promise.all() when:
- you need all results
- failure of one means the whole task failed
- the next step makes sense only if everything succeeded
Example uses:
- load page data from several endpoints
- load several related resources
- run multiple independent checks that all must pass
Diagram 7. When to use Promise.all()
Need all results?
-> Yes
-> Use Promise.all()
8. Promise.allSettled()
Promise.allSettled() is used when you want to wait for all promises to finish, no matter whether they succeed or fail.
Syntax
Promise.allSettled([promise1, promise2, promise3])
It also returns one promise.
But unlike Promise.all(), this returned promise always fulfills.
Diagram 8. Main idea of Promise.allSettled()
Promise.allSettled([...])
-> wait for all promises to finish
-> always fulfilled
-> returns array with status of each promise
9. Example of Promise.allSettled()
const p1 = Promise.resolve(1);
const p2 = Promise.reject("Rejected promise 2");
const p3 = Promise.resolve(3);
Promise.allSettled([p1, p2, p3])
.then(results => console.log(results));
Output
[
{ status: "fulfilled", value: 1 },
{ status: "rejected", reason: "Rejected promise 2" },
{ status: "fulfilled", value: 3 }
]
This method waits for all promises.
It does not fail just because one promise failed. Instead, it gives an array of result objects.
Very important correction
For rejected promises, the property is reason, not value.
- fulfilled gives
{ status: "fulfilled", value: ... } - rejected gives
{ status: "rejected", reason: ... }
Diagram 9. allSettled() result objects
Fulfilled promise
-> { status: "fulfilled", value: result }
Rejected promise
-> { status: "rejected", reason: error }
This is one of the most common beginner mistakes.
10. Why catch() is usually not needed for allSettled()
Because the promise returned by Promise.allSettled() itself does not reject in the normal use case.
It always gives you the final array.
So usually you just use:
.then(...)
Diagram 10. allSettled() behavior
Some promises succeed
Some promises fail
-> Promise.allSettled(...)
-> still fulfilled
11. When to use Promise.allSettled()
Use it when:
- you want information about every promise
- success and failure are both useful to inspect
- one failure should not destroy the whole result
Example uses:
- upload many files and show which succeeded
- run many independent API requests
- collect success/error info from many async tasks
Diagram 11. When to use Promise.allSettled()
Need result of every promise?
Need success and failure info?
-> Use Promise.allSettled()
12. Promise.race()
Promise.race() is used when you only care about the first settled promise.
Settled means:
- fulfilled
- or rejected
Syntax
Promise.race([promise1, promise2, promise3])
It returns one promise. That returned promise settles as soon as the first input promise settles.
Diagram 12. Main idea of Promise.race()
Promise.race([...])
-> watch all promises
-> first settled one wins
-> all others are ignored for the final result
13. Example: first fulfilled promise wins
const p1 = new Promise(resolve => {
setTimeout(() => resolve(1), 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject(2), 2000);
});
Promise.race([p1, p2])
.then(value => console.log(value))
.catch(error => console.log(error));
Output
1
p1 finished first after 1 second. It was fulfilled.
So Promise.race() also became fulfilled with value 1.
Diagram 13. Race with success first
p1 -> fulfilled after 1 second
p2 -> rejected after 2 seconds
-> Promise.race(...)
-> fulfilled with 1
14. Example: first rejected promise wins
const p1 = new Promise(resolve => {
setTimeout(() => resolve(1), 2000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject(2), 1000);
});
Promise.race([p1, p2])
.then(value => console.log(value))
.catch(error => console.log(error));
Output
2
p2 finished first after 1 second. It was rejected.
So Promise.race() also became rejected with 2.
Diagram 14. Race with rejection first
p1 -> fulfilled after 2 seconds
p2 -> rejected after 1 second
-> Promise.race(...)
-> rejected with 2
15. Does Promise.race() wait for the others?
No.
As soon as one promise settles, the result of Promise.race() is already decided.
The other promises may still continue in the background, but they do not matter anymore for the returned promise.
Diagram 15. Promise.race() stops caring
first promise settles
-> Promise.race(...) settles
-> other promises no longer affect the result
16. Promise.all() vs Promise.allSettled() vs Promise.race()
This is the most important comparison.
Promise.all()
- waits for all
- succeeds only if all succeed
- fails on first rejection
Promise.allSettled()
- waits for all
- never fails because of inner promise rejection
- gives status of every promise
Promise.race()
- waits only for the first settled promise
- result can be success or failure
Diagram 16. Full comparison
Promise.all()
-> all must succeed
Promise.allSettled()
-> all must finish
Promise.race()
-> first settled wins
17. Which one should I choose?
Use this simple rule:
Diagram 17. Choice guide
Need all results, and all must succeed?
-> Promise.all()
Need all results, even failed ones?
-> Promise.allSettled()
Need only the fastest result?
-> Promise.race()
18. Common beginner mistakes
Mistake 1. Thinking Promise.all() returns an array
It does not return an array directly. It returns a promise. That promise may later fulfill with an array.
Mistake 2. Thinking Promise.allSettled() can reject because one promise failed
It does not reject for that reason. It still fulfills with status objects.
Mistake 3. Using value for rejected results in allSettled()
Wrong:
{ status: "rejected", value: error }
Correct:
{ status: "rejected", reason: error }
Mistake 4. Thinking Promise.race() waits for all promises
It does not. It finishes when the first promise settles.
Mistake 5. Thinking Promise.all() result order depends on finish speed
It does not. The result order matches the input array order.
Diagram 18. Common mistakes summary
Promise.all() -> returns promise, not array
allSettled() -> rejected results use reason
race() -> first settled only
all() result order -> input order
19. Easy memory rules
Promise.all()
= all together, all must succeed
Promise.allSettled()
= all together, show every final result
Promise.race()
= fastest one wins
20. Quick summary
Promise.all()waits for all promises and fulfills with an array of results if all succeed.Promise.all()rejects when the first rejection happens.Promise.allSettled()waits for all promises and always fulfills with an array of result objects.- In
Promise.allSettled(), rejected promises usereason, notvalue. Promise.race()settles with the first settled promise, whether it is fulfilled or rejected.Promise.all()andPromise.allSettled()preserve input order in their result arrays.Promise.race()is useful when you only care about the fastest result.
21. Final conclusion
If you understand these ideas:
Promise.all()
Promise.allSettled()
Promise.race()
all must succeed
all must finish
fastest promise wins
then you already have a strong foundation for handling multiple promises in JavaScript.
These methods are very important in real projects because applications often run many asynchronous tasks at the same time.