How is `Promise.all()` different from `Promise.allSettled()`?
TL;DR
Promise.all() and Promise.allSettled() are both methods for handling multiple promises in JavaScript, but they behave differently. Promise.all() waits for all promises to resolve and fails fast if any promise rejects, returning a single rejected promise. Promise.allSettled(), on the other hand, waits for all promises to settle (either resolve or reject) and returns an array of objects describing the outcome of each promise.
Choosing an aggregation outcome
The methods start from the same set of inputs but differ in when and how the aggregate promise settles.
Use all() when every result is required for success; use allSettled() when every outcome must be inspected independently.
Promise.all()
Promise.all() takes an iterable of promises and returns a single promise that resolves when all of the input promises have resolved. If any of the input promises reject, the returned promise immediately rejects with the reason of the first promise that rejected.
Example
In this example, Promise.all() resolves with an array of results [3, 42, 'foo'] because all promises resolve successfully.
Failure case
In this example, Promise.all() rejects immediately with the reason 'error' because promise2 rejects.
Promise.allSettled()
Promise.allSettled() takes an iterable of promises and returns a single promise that resolves when all of the input promises have settled (either resolved or rejected). The returned promise resolves with an array of objects that each describe the outcome of each promise.
Example
In this example, Promise.allSettled() resolves with an array of result objects, each indicating the status and value of the promises.
Failure case
In this example, Promise.allSettled() resolves with an array of result objects, including the rejected promise with its reason.
When to use Promise.all() vs Promise.allSettled()
The choice comes down to a single question: if one of these operations fails, is the rest of the work still useful?
Use Promise.all() when partial success is invalid
- Prefetching everything a page needs before render: if any required call fails (auth, feature flags, current user), you want to render an error state, not a half-broken UI.
- Required independent reads: loading the current user, permissions, and feature configuration before rendering a page that needs all three.
- Gating UI on multiple checks: show the dashboard only if
getUser()ANDgetPermissions()both succeed. Fail-fast is the desired behavior.
Use Promise.allSettled() when partial success is acceptable
- Dashboard with multiple independent widgets: six analytics endpoints fan out in parallel. One slow or failing endpoint should not blank the rest of the dashboard.
- Bulk operations with per-item feedback: deleting 50 selected rows; the UI needs to show which succeeded and which failed, not abort on the first failure.
- Analytics or telemetry batches: sending several events where partial loss is acceptable; you want to know which fired even if one rejected.
If you would try/catch each call individually anyway, Promise.allSettled() is what you actually want.
Do not treat Promise.all() as a transaction. If several bookings or writes start together, one rejection does not cancel or roll back the others. Use a real transactional boundary where available, or design idempotency and compensating actions explicitly.
Failure-mode reference
| Input scenario | Promise.all() | Promise.allSettled() |
|---|---|---|
Empty iterable [] | Returns an already-fulfilled promise containing [] | Returns an already-fulfilled promise containing [] |
| Mix of promises and non-promise values | Wraps non-promises with Promise.resolve | Wraps non-promises with Promise.resolve |
| One rejection, others pending | Rejects immediately with first reason; others keep running but their results are ignored | Waits for all; returns one {status:'rejected'} entry |
Synchronous throw inside the iterable iterator | Returned promise rejects | Returned promise rejects |
Non-iterable input (e.g., undefined) | Returned promise rejects with TypeError | Returned promise rejects with TypeError |
| Result order vs resolution order | Results array preserves input order, not the order they resolved | Results array preserves input order |
Promise.all([]) does not reject or hang. Its returned Promise is already fulfilled with an empty array, but an attached .then() callback still runs asynchronously as a microtask. The result array always preserves input order, even when promise[2] resolves before promise[0].
Predict the output
Concurrent vs sequential awaits
These two snippets look almost identical but run very differently:
In this example, both calls have started before Promise.all() receives their promises. [await ..., await ...] evaluates left-to-right, so the second call starts only after the first fulfills.
Promise.allSettled() does not reject on per-promise failures
You will almost never put Promise.allSettled() inside a try/catch for the inner promises, since it does not throw on their rejections. To check for failures, filter on status === 'rejected' after the fact. (The returned promise can still reject if the input itself is invalid, for example, a non-iterable will produce a TypeError.)