Promise.any
Introduction
Promise.any(iterable) is the fastest-success combinator. It fulfils as soon as the first input fulfils and ignores earlier rejections. It rejects only when every input rejects, using an AggregateError containing all rejection reasons.
Why This Matters
Promise.any is easy to confuse with Promise.race. The interview distinction is that any wants the first fulfillment, while race wants the first settlement. A fast rejection can win race, but it cannot win any unless all inputs reject.
Theory
Exact semantics
Promise.any accepts an iterable of values, promises, or thenables. Plain values count as fulfilled inputs, so a plain value can make Promise.any fulfil.
It fulfils with the value from the first input that fulfils in time. Rejections before that are collected but do not reject the combined promise.
It rejects only if every input rejects. The rejection reason is an AggregateError, and error.errors contains the individual rejection reasons in input order. For an empty iterable, there is no possible fulfillment, so it rejects with an AggregateError whose errors array is empty.
Like other combinators, it does not cancel slower inputs after a winner fulfils.
Combinator comparison
| Combinator | Fulfils when | Rejects when | Result shape | Typical use |
|---|---|---|---|---|
Promise.all | Every input fulfils | First input rejects | Array of values in input order | All-or-nothing parallel work |
Promise.any | First input fulfils | Every input rejects | First fulfilled value or AggregateError | Redundant sources, fastest success |
Promise.allSettled | Every input settles | Never because of input rejection | Array of status objects in input order | Partial success reporting |
Promise.race | First input fulfils if it settles first | First input rejects if it settles first | First settled value or reason | Timeouts, first signal wins |
When to use it
Use Promise.any when you have multiple acceptable sources: fastest cache, fastest CDN mirror, primary and fallback providers, or redundant replicas. Do not use it when a fast rejection should fail the whole operation; use Promise.race or direct chaining for that.
Visual Diagrams
A rejects early --------- ignored for now B fulfils next ---------- Promise.any fulfils with B C fulfils later --------- ignored by combined promise Only if A, B, and C all reject does Promise.any reject.
Rejections are tolerated until no candidates remain.
inputs: [ A, B, C ] A rejects with reasonA B rejects with reasonB C rejects with reasonC Promise.any rejects with AggregateError errors: [ reasonA, reasonB, reasonC ]
The `errors` array follows input order, not rejection order.
Code Examples
Use the first successful mirror
A fast failure is ignored because another source may still fulfil.
Inspect AggregateError
When every input rejects, you can inspect all failure reasons.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function candidate(label, ms, shouldFulfill) {2 return new Promise(function (resolve, reject) {3 setTimeout(function () {4 console.log(label);5 if (shouldFulfill) {6 resolve(label);7 } else {8 reject(label);9 }10 }, ms);11 });12}13 14Promise.any([15 candidate('A reject', 10, false),16 candidate('B fulfill', 30, true),17 candidate('C fulfill', 20, true),18]).then(function (value) {19 console.log('any ' + value);20});Predict the output #2
1Promise.any([2 Promise.reject('x'),3 new Promise(function (resolve, reject) {4 setTimeout(function () {5 reject('y');6 }, 0);7 }),8]).catch(function (error) {9 console.log(error.name);10 console.log(error.errors.join(','));11});12 13console.log('sync');Coding Exercises
Implement a mini Promise.any
HardImplement promiseAny(iterable): fulfil with the first fulfilled input, ignore rejections until all inputs reject, reject empty input with AggregateError, and preserve final rejection reasons in input order.
Interview Questions
1How is `Promise.any` different from `Promise.race`?
Promise.any fulfils with the first fulfilled input and ignores rejections unless every input rejects. Promise.race settles with the first input to settle, whether fulfilled or rejected. A fast rejection rejects race but does not reject any while another input can still fulfil.
Follow-ups
- What error does `Promise.any` reject with?
- Does `Promise.any` cancel slower inputs after success?
2What happens when every input to `Promise.any` rejects?
The returned promise rejects with an AggregateError. The errors property contains all rejection reasons in input order. Empty input also rejects with AggregateError because there is no possible fulfillment.
Quiz
1. Which input outcome makes `Promise.any` fulfil?
2. If every input to `Promise.any` rejects, the returned promise rejects with...
Summary
- `Promise.any` fulfils with the first fulfilled input.
- Early rejections are ignored unless every input rejects.
- If all inputs reject, it rejects with `AggregateError` containing reasons in input order.
- Use it for redundant sources where any successful result is acceptable.
Cheat Sheet
Use when: fastest successful result wins.
Fulfil: first fulfillment by time.
Reject: only if all inputs reject → AggregateError.
Errors: error.errors preserves input order.
Empty: rejects with AggregateError.
Not race: fast rejection does not win unless all reject.