Promise APIs Comparison: all vs race vs any vs allSettled
JavaScript provides multiple Promise combinators.
They all start promises concurrently, but they differ in when they resolve/reject and what they return.
Understanding the differences prevents subtle bugs and improves performance.
๐ง Quick Overview#
| API | Resolves when | Rejects when | Typical use |
|---|---|---|---|
Promise.all | All promises resolve | Any promise rejects | All-or-nothing |
Promise.race | First promise settles | First promise settles | Timeout / fastest |
Promise.any | First promise resolves | All promises reject | First success |
Promise.allSettled | All promises settle | โ Never rejects | Collect results |
๐น Promise.all#
Behavior#
- Waits for all promises to resolve
- Rejects immediately if any promise rejects
await Promise.all([
fetch("/a"),
fetch("/b"),
fetch("/c"),
]);
Timeline#
A โโโโโโ
B โโโโโโผโโโบ resolve
C โโโโโโ
When to use#
โ
You need all results
โ One failure should stop everything
Common mistake#
await Promise.all(tasks); // crashes if one fails
If partial success is acceptable โ use allSettled.
๐น Promise.race#
Behavior#
- Settles as soon as the first promise settles
- That settlement can be resolve or reject
await Promise.race([
fetch("/data"),
timeout(3000),
]);
Timeline#
timeout โโโบ reject (wins)
fetch โโโโโโโโโโโโบ ignored
When to use#
โ
Timeouts
โ
First response wins
โ Not for โfirst success onlyโ
๐น Promise.any#
Behavior#
- Resolves on the first fulfilled promise
- Rejects only if all promises reject
- Rejection reason is an
AggregateError
const result = await Promise.any([
fetch("/cdn-1"),
fetch("/cdn-2"),
fetch("/cdn-3"),
]);
Timeline#
cdn-1 โ
cdn-2 โ
cdn-3 โ โโโบ resolve
When to use#
โ
Redundant endpoints
โ
Fallback strategies
โ When failures matter
๐น Promise.allSettled#
Behavior#
- Waits for all promises to settle
- Never rejects
- Returns status for each promise
const results = await Promise.allSettled([
fetch("/a"),
fetch("/b"),
fetch("/c"),
]);
Result shape#
[
{ status: "fulfilled", value: ... },
{ status: "rejected", reason: ... },
]
Timeline#
A โ
B โ
C โ โโโบ resolve with report
When to use#
โ
Logging
โ
Batch operations
โ
Partial success allowed
๐ง Mental Model#
Think of them as rules for waiting:
allโ everyone must succeedraceโ whoever finishes first decidesanyโ first success winsallSettledโ everyone reports back
โ ๏ธ Important Notes#
- All promises start immediately
- None of these APIs make JS parallel
- They only coordinate async results
This is still sequential:
await a();
await b();
This is concurrent:
await Promise.all([a(), b()]);
๐งช Real-World Use Cases#
| Scenario | Best API |
|---|---|
| Load page data | Promise.all |
| Add request timeout | Promise.race |
| Fallback API | Promise.any |
| Batch processing | Promise.allSettled |
โ Common Pitfalls#
1. Using all when failures are acceptable#
โ causes unnecessary crashes
2. Using race for โfirst successโ#
โ rejects too early
3. Forgetting AggregateError in any#
try {
await Promise.any(promises);
} catch (e) {
console.log(e.errors); // list of failures
}
โ Summary Table#
| API | Stops early | Rejects | Use for |
|---|---|---|---|
| all | โ | โ | Must-have-all |
| race | โ | โ | Fastest / timeout |
| any | โ | โ (all fail) | First success |
| allSettled | โ | โ | Full report |
โจ Final Takeaway#
Choose the Promise API based on failure behavior, not speed.
They all run concurrently โ the difference is when you stop waiting.
Start the discussion
Questions, corrections, a better approach? I read and reply to every comment.