Bitlyst

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

APIResolves whenRejects whenTypical use
Promise.allAll promises resolveAny promise rejectsAll-or-nothing
Promise.raceFirst promise settlesFirst promise settlesTimeout / fastest
Promise.anyFirst promise resolvesAll promises rejectFirst success
Promise.allSettledAll promises settleโŒ Never rejectsCollect 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 succeed
  • race โ†’ whoever finishes first decides
  • any โ†’ first success wins
  • allSettled โ†’ 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

ScenarioBest API
Load page dataPromise.all
Add request timeoutPromise.race
Fallback APIPromise.any
Batch processingPromise.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

APIStops earlyRejectsUse 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.

How did you like this post?

๐Ÿ‘0
โค๏ธ0
๐Ÿ”ฅ0
๐Ÿค”0
๐Ÿ˜ฎ0