Lập trình · 21/10/2026

JavaScript Promise.any: Select the First Fulfilled Result

One source fails early, but the application still wants usable data from another. Promise.any fits a requirement for one fulfillment. Define Promise success separately from data validity, and decide how to report the absence of a usable source.

JavaScript Promise.any: lấy kết quả thành công đầu tiên

One source fails early, but the application still wants usable data from another. Promise.any fits a requirement for one fulfillment. Define Promise success separately from data validity, and decide how to report the absence of a usable source.

Run each block inside an async function or with top-level await. All data stays in memory, without network calls or timers.

1. any does not select the first rejection like race

const jobs = [
  Promise.reject(new Error('source A failed')),
  Promise.resolve('source B data')
];
try {
  await Promise.race(jobs);
} catch (error) {
  console.log(error.message); // source A failed
}
console.log(await Promise.any(jobs)); // source B data

race follows the first settlement; any waits for a fulfillment. See MDN Promise.race and MDN Promise.any. These already-settled inputs demonstrate ordering, not network speed.

Use interchangeable candidates under an explicit contract. A screen requiring both a profile and its permissions cannot satisfy that requirement with just one arbitrary result. Specify the minimum required data before choosing a combinator.

2. Inspect the collected reasons when every candidate rejects

let failA;
let failB;
const a = new Promise((_, reject) => { failA = reject; });
const b = new Promise((_, reject) => { failB = reject; });
const selected = Promise.any([a, b]);
failB(new Error('B unavailable'));
failA(new Error('A unavailable'));
try {
  await selected;
} catch (error) {
  console.log(error instanceof AggregateError); // true
  console.log(error.errors.map(item => item.message).join('|'));
  // A unavailable|B unavailable
}

AggregateError collects rejection reasons in errors; see MDN AggregateError. Although B rejects first here, errors corresponds to input order A then B.

Keep source identifiers alongside input positions. The first collected reason is not necessarily the earliest failed dependency. Real rejection reasons need not be Error objects; reading message here relies on the Error instances created by this example.

The UI can use a short failure message while diagnostics retain the source association needed to investigate each dependency.

3. Empty input reaches the error path

try {
  await Promise.any([]);
} catch (error) {
  console.log(error instanceof AggregateError); // true
  console.log(error.errors.length); // 0
}

No candidates do not produce a default successful value. This example yields AggregateError with no collected reasons. Distinguish an unconfigured source list from sources that were attempted and all failed.

Also define a waiting policy: one rejected input and another forever-pending input do not establish that every candidate failed. Manage deadlines and cleanup where the application owns the operations.

4. false and invalid payloads can still be fulfillments

const flag = await Promise.any([
  Promise.resolve(false),
  Promise.resolve(true)
]);
const payload = await Promise.any([
  Promise.resolve({ ok: false, data: null }),
  Promise.resolve({ ok: true, data: 'ready' })
]);
console.log(flag); // false
console.log(payload.ok); // false

The false value is a normal fulfillment, and ok:false does not automatically reject its Promise. Validate each candidate against the required schema and business conditions before selection. Validation after selection does not make any resume searching for another result.

Selecting a result does not cancel remaining work. Account for the load of multiple sources and resource cleanup; any is not a retry policy or concurrency limit.

5. Review fallback selection

  • Do candidates provide equivalent replacement data?
  • Does each task validate the required result contract?
  • Is empty configuration handled explicitly?
  • Are errors associated with sources in input order?
  • Who owns deadlines and unselected work?

All eight bilingual blocks ran with Node.js, with additional early-rejection, non-Error reason and remaining-work checks. Real network sources and performance were not tested.

Discussion

Comments 0

Sign in to comment

You need an account to join the discussion and reply to other readers.

Sign inRegister

No comments yet. Be the first to share your thoughts.