Promise APIs Compared: all vs race vs any vs allSettled
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.