Q: What are the differences between Promise.all, Promise.allSettled, Promise.race, and Promise.any?

Answer:

All four are promise combinators — static methods that take an iterable of promises and return a single promise. They differ in when they settle and what they resolve or reject with.

Quick Comparison

MethodResolves whenRejects whenResult
Promise.allAll fulfillAny rejects (fail-fast)Array of values
Promise.allSettledAll settle (fulfilled or rejected)NeverArray of {status, value/reason}
Promise.raceFirst to settle (either way)First rejectionSingle value or reason
Promise.anyFirst fulfillmentAll reject (with AggregateError)Single value

Promise.all — fail-fast aggregation

const [user, posts, settings] = await Promise.all([
  fetchUser(),
  fetchPosts(),
  fetchSettings(),
]);

If any single promise rejects, the entire Promise.all rejects immediately. The other promises keep running in the background (they aren't cancelled), but their results are discarded.

[!NOTE] Use Promise.all only when partial failure is unacceptable. If a single optional resource fails, the whole batch is lost.

Promise.allSettled — never rejects

Introduced in ES2020. Waits for every promise regardless of outcome.

const results = await Promise.allSettled([fetchA(), fetchB(), fetchC()]);
results.forEach(r => {
  if (r.status === 'fulfilled') console.log('value:', r.value);
  else                          console.error('reason:', r.reason);
});

Ideal for dashboards where you want to render whatever succeeded and show errors for the rest.

Promise.race — first to finish

Returns whichever promise settles first, success or failure. Common for adding a timeout:

function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('timeout')), ms)
  );
  return Promise.race([promise, timeout]);
}

Promise.any — first success

Introduced in ES2021. Resolves on the first fulfillment; rejects only if every promise rejects, with an AggregateError containing all reasons.

try {
  const fastest = await Promise.any([
    fetch('https://mirror1/api'),
    fetch('https://mirror2/api'),
    fetch('https://mirror3/api'),
  ]);
} catch (e) {
  // e instanceof AggregateError; e.errors is the list of reasons
}

Decision Flow

   need every result?
        |
        +-- yes --> tolerate partial failure?
        |              |
        |              +-- yes --> Promise.allSettled
        |              +-- no  --> Promise.all
        |
        +-- no  --> need any success?
                       |
                       +-- yes --> Promise.any
                       +-- no  --> Promise.race  (first settle wins)

Common Pitfalls

  • Promise.all([]) resolves immediately with []. Promise.any([]) rejects with empty AggregateError.
  • Non-promise values are wrapped via Promise.resolve(value) — passing raw numbers is legal.
  • Combinators do not cancel in-flight work. Use AbortController to actually abort fetches when a race winner is determined.