Glossary / Promise.race
Promise.race
Promise.race(iterable) settles with the first input Promise (or value) that settles. The winner may fulfill or reject. It is useful for “first result wins” policies and timeouts, but racing a Promise does not cancel the losing operation. Losing work can continue consuming resources or produce side effects.
Timeout pattern and cancellation
const timeout = new Promise((_, reject) => {
setTimeout(() => reject(new Error("Timed out")), 2000);
});
await Promise.race([fetchData(), timeout]);
This rejects the caller’s wait after two seconds, but fetchData() may still run. For fetch, pair timeout logic with an AbortController and abort the underlying request. Cancel or clear the timeout when the operation wins to avoid unnecessary timer retention. A race with an empty iterable remains pending forever. A plain value participates as an already-fulfilled input, but Promise reactions still run asynchronously.
Timeouts should express a service-level deadline and be propagated through nested work where possible. If the first successful result is desired while failures are ignored, race is not enough; implement a policy that handles failures and cancels losers appropriately.
Interview questions
- What does Promise.race return? The first input to settle, fulfillment or rejection.
- Does race cancel losers? No.
- How build a real fetch timeout? Race or signal a deadline and abort the fetch operation.
- What happens with an empty iterable? The returned Promise remains pending.