Promise.all Failure Semantics

`Promise.all` fulfills only when every input promise fulfills, and it rejects as soon as any input rejects. The rejection reason comes from the first rejection observed by the combinator, while other already-started operations are not automatically canceled.

`Promise.all(iterable)` creates a combined promise representing all of its inputs. If every input fulfills, the combined promise fulfills with an array of fulfillment values in the same order as the inputs, regardless of which operation finishes first.

If any input rejects, the combined promise rejects immediately with that rejection reason. This is often called fail-fast behavior: the caller can stop waiting for the aggregate result as soon as one failure is observed.

Fail-fast does not mean cancellation. Promises do not provide automatic cancellation of their underlying asynchronous work. Other operations may continue running after `Promise.all` has rejected, and their later results or failures may still matter to the surrounding application.

This makes `Promise.all` useful when the overall operation is meaningful only if every dependency succeeds. If you need to observe every outcome instead, `Promise.allSettled` is usually the more appropriate combinator.

Key points

Interview questions

When should you choose `Promise.allSettled` instead of `Promise.all`?

Use `Promise.allSettled` when every operation should be allowed to finish and the application needs to inspect every outcome. It returns a result describing whether each input fulfilled or rejected. Use `Promise.all` when one failure makes the combined operation unsuccessful and individual partial results are not sufficient.

What happens when one promise passed to `Promise.all` rejects?

The combined promise rejects immediately with that rejection reason. It does not produce the successful values from the other inputs. The other asynchronous operations are not automatically canceled and may continue running.

Does `Promise.all` preserve the order of results?

Yes, when it fulfills, the resulting array follows the order of the input iterable. This is true even if later inputs finish before earlier ones. Completion timing does not determine the result-array positions.

Does `Promise.all` cancel promises after the first rejection?

No. `Promise.all` controls the state of its aggregate promise, not cancellation of the underlying operations. Network requests, timers, or other asynchronous work can continue after the aggregate has rejected. Cancellation requires a separate mechanism appropriate to the operation, such as `AbortController` for APIs that support abort signals.

What does 'fail-fast' mean for `Promise.all`?

Fail-fast means the aggregate promise rejects as soon as an input rejection is observed, rather than waiting for all inputs to settle. It does not imply that the underlying operations stop executing. This distinction matters when asynchronous work has side effects, consumes resources, or can outlive the caller's interest.