Promise.any()

Fulfills with the first promise to succeed, ignoring rejections until every input has failed.

Signature
Promise.any(iterable)
  • Added in JavaScript ES2021

Parameters

ParameterTypeDescription
$iterableIterableAn iterable, such as an Array, of promises. Values are awaited, so other thenables are resolved too; non-thenables are passed through as-is.

Return value

PromiseA Promise that fulfills with the value of the first input to fulfill. It rejects with an AggregateError if every input rejects, and is already rejected if the iterable is empty.

Errors

Rejects (rather than throws) with an AggregateError whose errors property holds every rejection reason in input order. TypeError if the argument is not iterable.

Promise.any() is the optimist of the combinators: it wants one success and tolerates any number of failures on the way there. It fulfills as soon as the first input fulfills and ignores every rejection unless all of them reject.

The AggregateError

When everything fails, the rejection reason is a single AggregateError whose errors property is an array of all the individual reasons, in input order rather than failure order. Reading err.message alone gives you a generic string like "All promises were rejected" — the diagnosis you actually want is in err.errors.

any() versus race()

Both settle early, but on different criteria. race() settles on the first promise to settle, so a fast rejection wins and rejects the whole thing. any() settles on the first promise to fulfill, so a fast rejection is simply skipped. Reach for any() when you have several ways to get the same answer and only need one to work.

Edge case

An empty iterable rejects immediately with an AggregateError holding an empty errors array — the mirror image of Promise.all([]), which fulfills.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Query several mirrors and use whichever responds successfully first
  • Fall back from cache to database to backup without nesting catch blocks
  • Race redundant endpoints where some are expected to be down
  • Collect every failure reason in one place when no source works

Frequently asked questions

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

any() waits for the first fulfillment and ignores rejections unless all inputs reject; race() settles with the first result of any kind, so an early rejection rejects the whole thing.

How do I read the individual errors from Promise.any?

Access the errors property on the AggregateError: catch(e => e.errors) gives an array of every rejection reason, in the order the promises were passed.

What does Promise.any([]) do?

It rejects immediately with an AggregateError whose errors array is empty, because there was never any input that could fulfill.

More examples

Empty input, and non-promise values

The empty iterable rejects straight away with an AggregateError carrying zero errors. In the second call the plain string counts as an immediately fulfilled value, so it wins over the rejection beside it.

Example · javascript
try {
  await Promise.any([]);
} catch (e) {
  console.log("empty:", e.name, e.errors.length);
}

console.log(await Promise.any([Promise.reject(new Error("r")), "plain"]));

any() versus race() on the same inputs

Identical inputs, opposite outcomes. any() skips the 5ms rejection and waits for the 20ms success; race() takes the 5ms rejection because it was simply first to settle.

Example · javascript
const boom = (ms, m) => new Promise((_, rj) => setTimeout(() => rj(new Error(m)), ms));
const delay = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
const list = () => [boom(5, "early failure"), delay(20, "eventual success")];

console.log("any  ->", await Promise.any(list()));
console.log("race ->", await Promise.race(list()).catch((e) => "rejected: " + e.message));

Discussion

  • Be the first to comment on this lesson.