Promise.all
Introduction
Promise.all(iterable) is the fail-fast combinator for independent async work that must all succeed. It observes every input, fulfils with an array of values in input order, and rejects as soon as the first input rejects.
Why This Matters
Promise.all is the default answer for parallel independent work, but interviewers expect exact details: output order is input order, rejection is fail-fast, non-promises are allowed, empty input fulfils with [], and fail-fast does not cancel in-flight work.
Theory
Exact semantics
Promise.all accepts any iterable of values, promises, or thenables. Each input is normalised through promise resolution, so plain values count as already fulfilled.
It fulfils only when every input fulfils. The fulfillment value is an array whose indexes match the input order, not completion order.
It rejects as soon as the first input rejects in time. The rejection reason is that first rejection reason. Other operations are not cancelled; their timers, network work, or side effects may continue even though the combined promise has already rejected.
For an empty iterable, Promise.all([]) returns an already fulfilled promise with [], but attached .then callbacks still run asynchronously as microtasks.
Combinator comparison
| Combinator | Fulfils when | Rejects when | Result shape | Typical use |
|---|---|---|---|---|
Promise.all | Every input fulfils | First input rejects | Array of values in input order | All-or-nothing parallel work |
Promise.any | First input fulfils | Every input rejects | First fulfilled value or AggregateError | Redundant sources, fastest success |
Promise.allSettled | Every input settles | Never because of input rejection | Array of status objects in input order | Partial success reporting |
Promise.race | First input fulfils if it settles first | First input rejects if it settles first | First settled value or reason | Timeouts, first signal wins |
When to use it
Use Promise.all when tasks are independent and the next step requires every result: profile plus permissions, multiple validations that must all pass, or independent calculations. Use Promise.allSettled when partial results are acceptable. If you need cancellation after a failure, build it into the underlying operations separately.
Visual Diagrams
inputs: [ A, B, C ]
settle time: C first, A second, B third
Promise.all output after all fulfil:
[ valueA, valueB, valueC ]
Completion order does not change array indexes.The returned array is indexed like the input iterable.
A starts -------- resolves later B starts ---- rejects first ---- Promise.all rejects with B reason C starts --------------- resolves later A and C can still finish because Promise.all only stops waiting.
The combined promise rejects early, but underlying work continues unless separately cancelled.
Code Examples
Parallel work with ordered results
The fastest task can finish first, but the result array still follows input order.
Fail-fast rejection
The first rejection rejects the combined promise. Other promises are not cancelled automatically.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function task(label, ms, shouldReject) {2 return new Promise(function (resolve, reject) {3 setTimeout(function () {4 console.log('settled ' + label);5 if (shouldReject) {6 reject(label);7 } else {8 resolve(label);9 }10 }, ms);11 });12}13 14Promise.all([15 task('A', 30, false),16 task('B', 10, true),17 task('C', 20, false),18])19 .then(function (values) {20 console.log('all ' + values.join(','));21 })22 .catch(function (reason) {23 console.log('catch ' + reason);24 });Predict the output #2
1Promise.all([Promise.resolve('A'), 'B'])2 .then(function (values) {3 console.log(values.join(','));4 });5 6console.log('sync');Coding Exercises
Implement a mini Promise.all
HardImplement promiseAll(iterable): accept values or promises, preserve input order, resolve to [] for empty input, fulfil only after all inputs fulfil, and reject as soon as the first input rejects.
Interview Questions
1Explain the exact behavior of `Promise.all`.
Promise.all takes an iterable of values or promises and returns a promise. It fulfils when every input fulfils, with values in input order. It rejects as soon as the first input rejects, using that reason. Empty input fulfils with []. It does not cancel other work after a rejection.
Follow-ups
- Does completion order affect the result array?
- What should you use when partial failures are acceptable?
2If one promise in `Promise.all` rejects, what happens to the other promises?
The combined promise rejects immediately with the first rejection reason, but the other promises are not cancelled. They may still fulfil, reject, log, mutate state, or perform side effects. Cancellation must be built into the underlying operations separately.
Quiz
1. What does `Promise.all([slowA, fastB])` return when both fulfil?
2. When does `Promise.all` reject?
Summary
- `Promise.all` fulfils only when every input fulfils.
- Its fulfillment array preserves input order, not completion order.
- It rejects fast on the first rejection reason and does not cancel other work.
- Use it for all-or-nothing parallel work; use `allSettled` for partial success reporting.
Cheat Sheet
Use when: independent tasks must all succeed.
Fulfil: all inputs fulfil → array in input order.
Reject: first rejection by time.
Empty: fulfils with [].
Values: non-promises are allowed.
Caveat: fail-fast does not cancel in-flight work.