Promise.race vs Promise.any: What Sets Them Apart?
Learn the difference between Promise.race and Promise.any, their settlement rules, AggregateError, and real use cases.
Expected Interview Answer
Promise.race settles as soon as any one input promise settles — whether it fulfills or rejects — mirroring whatever that first promise did, while Promise.any settles as soon as the first promise fulfills and ignores rejections unless every single promise rejects, in which case it rejects with an AggregateError.
Promise.race is purely about speed and order: the very first promise to reach any settled state, success or failure, determines the outcome, so it is commonly used for timeout patterns where you race a real operation against a timer promise that rejects after a deadline. Promise.any, introduced in ES2021, is specifically about getting the first success while tolerating individual failures — it keeps waiting through rejections and only surfaces a result once one promise fulfills, or, if all of them reject, it rejects with a single AggregateError whose errors property holds every individual rejection reason. A classic use case for any is querying several redundant mirrors or fallback API endpoints for the same data and taking whichever one responds successfully first, without caring that some slower or broken mirrors failed along the way. Mixing the two up is a real bug: using race for redundant-endpoint fallback risks accepting the first rejection as the final result even though a working mirror was about to succeed.
- Promise.race is ideal for implementing request timeouts against a competing timer promise
- Promise.any is ideal for “fastest successful response wins” across redundant sources
- any tolerates individual failures without failing the whole operation prematurely
- race gives predictable first-settled-wins semantics regardless of success or failure
AI Mentor Explanation
Promise.race is like declaring the match outcome based on whichever event happens first — the winning run or the innings collapsing — whichever comes first decides the result, win or loss. Promise.any is like a set of parallel net sessions where you only care about the first bowler who successfully clean-bowls the target stump, ignoring any bowler whose attempt misses, and only declaring total failure if every bowler in the group misses. Race cares about first-to-settle regardless of outcome; any specifically waits for first success while shrugging off failures along the way. That distinction is exactly Promise.race versus Promise.any.
Step-by-Step Explanation
Step 1
Clarify what “first” should mean
Decide if you need the first settled outcome regardless of type (race) or specifically the first successful outcome (any).
Step 2
Promise.race settles on any settlement
The first promise to fulfill or reject determines race’s outcome immediately, mirroring that result.
Step 3
Promise.any ignores rejections until the end
It keeps waiting through failures and only settles on the first fulfillment.
Step 4
Handle Promise.any total failure
If every input promise rejects, any rejects with an AggregateError whose errors array holds all individual reasons.
What Interviewer Expects
- Correct distinction: race settles on first settlement of any kind, any settles on first success only
- Knowledge that Promise.any rejects with AggregateError only if everything fails
- A concrete example: race for timeouts, any for redundant-source fallback
- Awareness that Promise.any is ES2021, newer than race
Common Mistakes
- Using Promise.race for redundant-endpoint fallback, accidentally accepting an early failure as final
- Forgetting Promise.any throws AggregateError, not a plain Error, on total failure
- Assuming Promise.any waits for all promises before resolving (it resolves on first success)
- Confusing race’s “first settled” with any’s “first fulfilled” semantics
Best Answer (HR Friendly)
“Promise.race just cares about whichever finishes first, whether that is a success or a failure. Promise.any specifically waits for the first success and ignores failures along the way, only giving up if literally everything fails. So race is great for timeouts, and any is great for trying several backup sources and taking whichever one works first.”
Code Example
function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timed out')), ms)
)
// race: first settlement wins, success or failure
return Promise.race([promise, timeout])
}
async function fetchFromFastestMirror(urls) {
try {
// any: first successful response wins, failed mirrors are ignored
const response = await Promise.any(urls.map(url => fetch(url)))
return response.json()
} catch (err) {
// err is an AggregateError only if every mirror failed
console.error('All mirrors failed:', err.errors)
throw err
}
}Follow-up Questions
- How would you implement a request-timeout wrapper using Promise.race?
- What does AggregateError.errors contain when Promise.any fully fails?
- Which ECMAScript version introduced Promise.any?
- How would you cancel the losing operations after Promise.race settles?
MCQ Practice
1. What determines the outcome of Promise.race?
Promise.race mirrors whichever input promise settles first, regardless of success or failure.
2. When does Promise.any reject?
Promise.any tolerates individual failures and only rejects (with AggregateError) if all promises reject.
3. Which is the better fit for a fetch-with-timeout pattern?
Racing the real request against a timer promise that rejects after a deadline is the classic Promise.race use case.
Flash Cards
Promise.race settles on? — Whichever input promise settles first, fulfilled or rejected.
Promise.any settles on? — The first fulfillment; it ignores rejections unless all promises reject.
Promise.any total-failure error type? — AggregateError, with an errors array of every rejection reason.
Classic use case for race? — Timeout pattern: race a real operation against a rejecting timer promise.