When to Use promise.allsettled in JavaScript

In Brief
Use Promise.allSettled() when the next step needs every fulfilled and rejected outcome, and partial results remain valid. It does not make failures harmless, cancel unfinished work, or replace fail‑fast behaviour when an operation must succeed as a whole. Handle every rejected result explicitly and keep its identity beside its reason.
Suppose a dashboard loads a profile, recent orders, and service notices. The three panels are useful independently. If the orders request fails, hiding the profile and notices does not make the dashboard more correct; it only turns one partial failure into an empty page.
Now consider three writes required to publish a release. If any write fails, the operation must not be described as successful. These cases need different aggregate policies, even if both begin with three promises.
The Failure Policy Comes First
Choose the combinator from the product decision, not because one method is newer.
| Question | Promise.all() | Promise.allSettled() |
|---|---|---|
| When does the returned promise settle? | after all fulfil, or after the first input rejection | after every input settles normally |
| What information is returned? | all fulfilled values, or one rejection reason | one result object for every input |
| Result order | input order | input order |
| Suitable policy | complete success is required | every outcome is needed |
Both methods receive promises or other values. They do not start work merely by being named. Often the operations have already begun whilst the promise list is being constructed.
That also means changing Promise.all() to Promise.allSettled() changes how completion is reported, not when each executor, request, or timer begins. Review promise creation separately if start time or resource use is part of the bug.
What Promise.all() Stops Returning after Rejection
Use a fixed set of dashboard tasks:
const tasks = [ { name: 'profile', promise: loadProfile() }, { name: 'orders', promise: loadOrders() }, { name: 'notices', promise: loadNotices() },];With Promise.all(), the first rejected input rejects the combined promise:
try { const values = await Promise.all( tasks.map((task) => task.promise) ); renderDashboard(values);} catch (error) { renderDashboardFailure(error);}That is fail‑fast aggregation. If loadOrders() rejects first, the combined promise provides its reason rather than an array containing the profile and notices. The other operations are not cancelled; they may still fulfil later, but their values do not arrive through this Promise.all() result.
This is correct when all values form one valid result. It is a poor fit when each panel can make its own honest success or failure decision.
What allSettled() Returns
Promise.allSettled() waits for each input promise to become fulfilled or rejected, then fulfils its returned promise with result objects:
const outcomes = await Promise.allSettled( tasks.map((task) => task.promise));For the dashboard, the array might have this shape:
[ { status: 'fulfilled', value: { name: 'Ada' } }, { status: 'rejected', reason: new Error('Orders unavailable') }, { status: 'fulfilled', value: ['Maintenance at 18:00'] },]A fulfilled result has status: 'fulfilled' and a value. A rejected result has status: 'rejected' and a reason. Do not read value before checking the status, and do not filter rejected objects away merely to make the successful path shorter.
The array follows input order, not completion order. Orders may reject first and the profile may fulfil last; their result objects still occupy indexes one and zero because those are their input positions. The ECMAScript 2020 `Promise.allSettled()` algorithm assigns an index as it consumes each input and stores the corresponding result at that index.
Rejection of an ordinary input becomes a rejected result object rather than rejecting the aggregate. That does not justify saying the method can never fail under any circumstances: errors whilst obtaining or iterating the input are a separate part of the call's contract.
A Partial‑Failure Example
Keep task identity next to each promise, then branch symmetrically on every outcome:
const outcomes = await Promise.allSettled( tasks.map((task) => task.promise));let failureCount = 0;outcomes.forEach((outcome, index) => { const task = tasks[index]; if (outcome.status === 'fulfilled') { renderPanel(task.name, outcome.value); return; } failureCount += 1; renderPanelFailure(task.name); reportFailure(task.name, outcome.reason);});if (failureCount > 1) { showDashboardWarning('Several sections could not be loaded.');}The user sees the valid profile and notices, plus an explicit unavailable state for orders. The failure is logged with the task name and reason. A stated rule escalates multiple failures.
This is more useful than the tempting shortcut:
const values = outcomes .filter((outcome) => outcome.status === 'fulfilled') .map((outcome) => outcome.value);That loses both rejected reasons and their positions. It may also associate the remaining values with the wrong panels. Partial failure is a policy to handle, not an excuse to erase evidence.
When Not to Use It
Use Promise.all() when incomplete success is not a usable product state. A release which requires a manifest, an asset record, and a deployment record should not announce completion after two fulfilled writes and one rejection. Better still, consistency‑critical writes may need a server‑side transaction rather than any client‑side promise combinator.
Do not group dependent work merely to collect outcomes. If the second operation needs the first operation's value, express that dependency in sequence. allSettled() does not make invalid scheduling valid.
Independence also does not mean unlimited volume. Starting ten thousand requests and passing their promises to allSettled() creates a resource problem which the combinator does not limit. Concurrency controls and retry policy are separate decisions.
Finally, a security or permissions failure may require the whole view to stop rather than display adjacent data. The appropriate policy comes from the meaning of the failure, not from a preference for partial rendering.
Support and Failure Visibility
Promise.allSettled() entered the ECMAScript 2020 specification after reaching Stage 4 in 2019. By December 2020 it was available in Chrome 76, Firefox 71, Safari 13, Chromium‑based Edge 79, and Node 12.9. It was not available in Internet Explorer.
If an older runtime remains in scope, decide whether a standards‑compatible polyfill belongs in the bundle. Transpiling async syntax does not itself add the Promise.allSettled() method. The TC39 proposal archive records the proposal history, engine implementations, and reference polyfill.
Whatever the runtime, test visible failure handling as carefully as fulfilled values. Assert result shapes, input ordering, log or render every rejection, and make sure the interface does not rely on colour alone to distinguish a missing panel.
Wrapping Up
Promise.all() answers whether a group can produce one complete success. Promise.allSettled() describes every outcome so the application can decide what remains useful.
Use the latter only when the tasks are suitably independent and the next step genuinely needs all outcomes. Then keep identity, value, and reason intact. A settled rejection is still a failure; the method simply gives your code a deliberate place to deal with it.
Postscript
Aug 2026: This article forms part of an archive restored from a previous version of my website. Its original publication date is accurate. During the restoration, I reviewed and updated it where appropriate for formatting, imagery, broken links, code correctness, and current internal references, whilst preserving the original technical context and intent.
The core Promise.allSettled() behaviour described in this article remains current. Later JavaScript features have expanded the language around asynchronous programming, but the decision of when to use Promise.allSettled() instead of Promise.all() remains unchanged.