tryjs.app

JavaScript Promise.race & allSettled — Combinator Examples

Learn Promise.race and Promise.allSettled in JavaScript with runnable examples. Timeouts, first-to-finish wins, and collecting every outcome including failures.

Promise.race & allSettled

Advanced Promise combinators

javascriptAsync Patterns
const delay = (ms, val) =>
  new Promise(r => setTimeout(() => r(val), ms));
const fail = (ms, msg) =>
  new Promise((_, reject) => setTimeout(() => reject(new Error(msg)), ms));

(async () => {
  // race: first to settle wins
  const fastest = await Promise.race([
    delay(200, "slow"),
    delay(50, "fast"),
    delay(100, "medium"),
  ]);
  console.log("race winner:", fastest);

  // race as timeout
  try {
    const result = await Promise.race([
      delay(500, "real result"),
      fail(200, "Timeout after 200ms"),
    ]);
    console.log("got:", result);
  } catch (e) {
    console.error("error:", e.message);
  }

  // allSettled: every outcome
  const outcomes = await Promise.allSettled([
    delay(50, "ok"),
    fail(100, "oops"),
    delay(75, "also ok"),
  ]);
  outcomes.forEach((o, i) => {
    if (o.status === "fulfilled") console.log(`${i}: ✓ ${o.value}`);
    else console.log(`${i}: ✗ ${o.reason.message}`);
  });
})();

Overview

Promise.race and Promise.allSettled complete the 'combinator' family alongside Promise.all and Promise.any. race settles with whichever input settles first — useful for timeouts and first-response-wins patterns. allSettled waits for everything and returns per-promise outcome objects, so a single failure doesn't discard the rest. Together they cover the cases Promise.all can't: early exit and partial-success reporting.

How It Works

Promise.race — first settlement wins

Returns a promise that settles as soon as any input settles — resolved or rejected. Common use: racing a real operation against a timeout promise to impose a maximum wait.

Promise.allSettled — every outcome

Waits for all input promises regardless of success or failure, then resolves with an array of { status: 'fulfilled'|'rejected', value|reason } objects. Never rejects itself.

Promise.any — first success

A close cousin: resolves with the first fulfilled result, ignoring rejections. Only rejects if all inputs reject, with an AggregateError collecting every failure.

Picking the right combinator

all: everything must succeed. allSettled: collect everything, success or not. race: whoever finishes first wins (good or bad). any: whoever succeeds first wins.

Common Mistakes

  • Using Promise.race for 'first success' — a fast rejection wins and kills the race. Use Promise.any for that.
  • Assuming allSettled rejects — it never does; always check each entry's status field.
  • Racing an API call against setTimeout without also rejecting the timeout, so the API still runs even after the timeout 'wins'.
  • Forgetting that race doesn't cancel losers — they keep running in the background until they complete or crash.

When to Use It

Use race for timeouts and 'first response wins' patterns. Use allSettled when you need to report on every operation regardless of outcome (dashboards, batch status). Use any when a single success is enough and you want to ignore failures.

Frequently Asked Questions

What is the difference between Promise.race and Promise.any?

Promise.race settles with whichever promise settles first — resolved or rejected. Promise.any waits for the first fulfilled promise and ignores rejections until all reject. Use race for timeouts, any for 'first success wins'.

When should I use Promise.allSettled?

When you need to know the outcome of every promise regardless of success or failure — dashboards, batch-processing reports, retries that care about which subset failed. Unlike Promise.all, a single rejection doesn't discard everything.

Can Promise.race be used for timeouts?

Yes — race your real promise against a setTimeout-based promise that rejects after N ms. Whichever settles first wins. Note that losers keep running in the background; for true cancellation use AbortController.

Does Promise.allSettled ever reject?

No — it always fulfills, with an array of per-promise outcome objects. Each entry has { status: 'fulfilled', value } or { status: 'rejected', reason }. You inspect each result individually.