Promise.allSettled()

The method for when partial success is a real outcome. Because it never rejects, the try/catch around it is dead code — the failures arrive as data instead.

Promise static methodES2020Live demo
Common call
const rs = await Promise.allSettled(tasks)
Returns
status objects, one per input
Replaces
Promise.all wrapped in per-task catch handlers
Watch out
values are nested under .value — not the value itself
Promise.allSettled(iterableiterable — Any iterable of promises or plain values. Non-promises are reported as fulfilled.type: iterable · required)
→ Promise<Array>

Demo

Live evaluation
Try:
Inputs
jsonstringJSON list of [outcome, value, ms]
Output
await Promise.allSettled(JSON.parse('[["ok",1,10],["err","boom",20]]').map(([k, v, ms]) => new Promise((res, rej) => setTimeout(() => k === 'ok' ? res(v) : rej(new Error(v)), ms))))
Pending…

Each input is [outcome, value, delay in ms]: 'ok' fulfils with the value, anything else rejects with an Error carrying it. Every input produces a status object, in input order, and the combined promise never rejects — even the second case, where everything failed, resolves normally with two 'rejected' entries. That is why a try/catch around allSettled is dead code: failures arrive as data. Note the values are nested under value and reason, not returned bare as Promise.all would.

Parameters

NameTypeRequiredDescription
iterableiterableyesAny iterable of promises or plain values. Non-promises are reported as fulfilled.

Return value

Promise<Array> — A Promise for an array of objects — {status: "fulfilled", value} or {status: "rejected", reason} — in input order. It never rejects.

Common patterns

Keep what succeeded
Filter on status, then unwrap.
const rs = await Promise.allSettled(tasks);
const ok = rs.filter(r => r.status === "fulfilled").map(r => r.value);
Report what failed
The reasons are all available at once.
const errors = rs.filter(r => r.status === "rejected").map(r => r.reason);
Fail fast instead
Promise.all when any failure should abort.
const all = await Promise.all(tasks);

Examples

1. Mixed outcomes
await Promise.allSettled([Promise.resolve(1), Promise.reject(new Error("boom"))])
Returns
[{status: "fulfilled", value: 1}, {status: "rejected", reason: Error}]
2. It never rejects
await Promise.allSettled([Promise.reject(1)]).then(() => "resolved")
Returns
'resolved'
3. Empty array
await Promise.allSettled([])
Returns
[]
4. Order is input order
await Promise.allSettled([slow, fast])
Returns
slow first, regardless of timing
5. Unwrapping
rs.filter(r => r.status === "fulfilled").map(r => r.value)
Returns
the successful values
6. Promise.all differs
await Promise.all([Promise.reject(new Error("boom"))])
Returns
throws Error: boom

Pitfalls

1. The values are wrapped
Every entry is a status object, so the array you get back is not the array of results you would get from Promise.all. Code migrated from all without unwrapping ends up treating {status, value} objects as if they were the data.
Status objects
const [a] = await Promise.allSettled([Promise.resolve(1)]);
a
{status: "fulfilled", value: 1}
Unwrap
const [a] = await Promise.allSettled([Promise.resolve(1)]);
a.value
1
2. try/catch around it is dead code
It never rejects, so the catch block can never run. That is easy to miss when converting from Promise.all — the error handling looks intact and silently stops working, and failures pass through as data nobody inspects.
Never runs
try { await Promise.allSettled(t); } catch { /* unreachable */ }
failures ignored
Check the statuses
const bad = rs.filter(r => r.status === "rejected");
if (bad.length) report(bad);
failures handled
3. It still does not cancel anything
Like Promise.all, it waits for every input to settle — so the slowest failure sets the total time. If one task can hang, allSettled hangs with it; add a timeout per task or race each against one.
Waits for the hang
await Promise.allSettled([hangsForever, quick])
never settles
Time each one out
tasks.map(t => Promise.race([t, timeout(5000)]))
bounded
4. ES2020 — check your runtime
Node 12.9+ and 2019-era browsers. The pre-2020 equivalent is mapping each promise to one that cannot reject, which is worth recognising in older code.
Missing
Promise.allSettled(tasks)
TypeError: Promise.allSettled is not a function
Polyfill shape
Promise.all(tasks.map(p =>
  p.then(value => ({status: "fulfilled", value}),
         reason => ({status: "rejected", reason}))))
equivalent

When to use

Use it
  • Several independent tasks where partial success is useful
  • Dashboards and batch jobs — report what failed, render what worked
  • Cleanup and teardown, where every step should be attempted
  • Collecting all validation errors rather than the first
Reach for something else
  • Any failure should abort → Promise.all
  • You want the first success → Promise.any
  • You want the first result at all → Promise.race
  • A task may hang → bound each one with a timeout

Notes

Complexity
O(n); wall-clock time is the SLOWEST input, success or failure
Return
A new Promise that always fulfils
CPython impl
V8: Builtins-promise-allsettled
Memory
Holds a status object per input until all settle
Thread-safe
Single-threaded

FAQ

all when every task must succeed for the outcome to mean anything — a transaction, a multi-step save. allSettled when the tasks are independent and knowing which ones failed is more useful than aborting.

History

ES2015
Promise.all and race shipped; partial success had no built-in expression.
ES2020
allSettled added alongside Promise.any.