Promise Combinators
Combine multiple promises with Promise.all, allSettled, race, and any — the patterns behind parallel API calls and resilient batch jobs.
Real features rarely await one promise. Dashboards fetch user, settings, and notifications together. Batch jobs process many records and need to know which failed. Promise combinators encode these policies: fail-fast, wait-for-all, first-wins, or first-success. Picking the wrong combinator causes silent partial failures or unnecessary total failure.
Promise.all — all succeed or one failure rejects
Promise.all takes an iterable of promises and returns one promise that fulfills with an array of results in order. If any input rejects, the whole thing rejects immediately with that reason — other in-flight work still completes but results are ignored. Use when you need every piece — loading a page shell where missing data breaks the UI.
All: ['A', 'B', 'C']
All failed: failPromise.allSettled — never short-circuit
allSettled waits for every input to settle and returns { status, value | reason } objects. No single failure rejects the batch — ideal for bulk operations where you report per-item errors (import 100 rows, show which rows failed). ES2020 added this specifically to fix Promise.all's all-or-nothing behavior.
Success count: 2
Fail count: 1Promise.race and Promise.any
Promise.race settles when any input settles — first fulfillment or first rejection wins. Use for timeouts: race(fetch(url), delay(5000).then(() => throw timeout)). Promise.any (ES2021) fulfills on the first success — ignores rejections until all fail. Useful for trying mirror CDN endpoints until one responds.
fast
cdn2 ok| Combinator | Resolves when | Rejects when |
|---|---|---|
| Promise.all | All fulfill | First rejection |
| Promise.allSettled | All settled | Never |
| Promise.race | First settle (ok or fail) | First settle if rejection |
| Promise.any | First fulfillment | All reject (AggregateError) |
Choosing a combinator is choosing a failure policy: Promise.all for atomic page loads, allSettled for bulk imports with per-row error reports, race for timeouts, any for CDN fallback. Document the policy in code comments when the choice is not obvious — future maintainers will thank you during outages.
Dashboard loaders often fan out five or six requests on mount. If one entitlement check fails but the rest succeed, allSettled lets you render partial UI with error banners instead of a blank screen from Promise.all rejection. Match combinator to product requirements, not habit.
Production fan-out pattern
Parallel fetch with bounded concurrency is a common extension of Promise.all. For fifty IDs, map each to fetchItem(id) inside Promise.all only if the API tolerates burst traffic. Otherwise chunk into batches of five or use a pool — the combinator stays all, the scheduling strategy changes.
- 1all — every success required; one fail kills batch
- 2allSettled — inspect each result; partial success OK
- 3race — first finished wins (timeouts)
- 4any — first success wins (fallback mirrors)
- 5Next lesson: async error handling in production