2HAASStart a project
All posts

Code Snippets

Promise.allSettled: keep the results that succeeded

Promise.all throws away every result when one request fails. Promise.allSettled waits for all of them and reports each outcome, so one failure cannot empty a page.

The 2HAAS team2 min read

A dashboard loads a profile, a list of orders and a set of offers. The offers service has a bad moment. With Promise.all, the whole page fails, although two of the three requests worked.

// One rejection rejects everything. The other results are lost.
const [profile, orders, offers] = await Promise.all([getProfile(), getOrders(), getOffers()]);

Promise.allSettled is built for this case.

How it works

It waits until every promise has finished, whether it succeeded or failed, and it never rejects. You get one result object per promise, in the same order.

const results = await Promise.allSettled([getProfile(), getOrders(), getOffers()]);

// [
//   { status: "fulfilled", value: { name: "Rafi" } },
//   { status: "fulfilled", value: [/* orders */] },
//   { status: "rejected", reason: Error("503 Service Unavailable") }
// ]

A fulfilled result has a value. A rejected one has a reason.

Use the successes, report the failures

const [profile, orders, offers] = results.map((result) =>
  result.status === "fulfilled" ? result.value : null,
);

results
  .filter((result) => result.status === "rejected")
  .forEach((result) => logger.warn({ err: result.reason }, "Dashboard section failed"));

render({ profile, orders, offers }); // offers is null, so that section shows a retry link

The page shows the profile and the orders, and the offers section explains that it could not load. One failure stays one failure.

Choosing the right combinator

Method Resolves when Rejects when Use it for
Promise.all All succeed Any one fails Steps that are all required
Promise.allSettled All have finished Never Independent tasks where partial results are useful
Promise.any The first one succeeds All fail Trying several sources for the same thing
Promise.race The first one finishes The first one fails Timeouts and "whichever answers first"

Promise.all is still the right choice when the results depend on each other. If you cannot create an order without both the stock check and the payment, failing fast is what you want.

Two things to remember

You must check the statuses. Because allSettled never rejects, a try/catch around it catches nothing. If you ignore the rejected entries, the errors disappear silently.

It waits for everything. One hanging request delays the whole result. Give each request a timeout:

const getOffers = () => fetch("/api/offers", { signal: AbortSignal.timeout(3000) });

Where it fits

  • loading independent sections of a page,
  • sending notifications to many recipients,
  • running a batch of uploads and reporting which ones failed,
  • cleanup steps that should all be attempted.

For the wider pattern of catching and reporting failures, see async error handling in JavaScript.

Keep reading

  1. Tech Tips2 min read

    Async error handling in JavaScript: try/catch done right

    Unhandled promise rejections crash Node.js services and leave browser apps quietly broken. Catch async errors with try/catch, .catch and a global safety net.

  2. Code Snippets2 min read

    Web Workers: move heavy work off the main thread

    Heavy JavaScript freezes the page because it shares a thread with the interface. A Web Worker runs that work in the background. A working example and the limits to know.

  3. Code Snippets2 min read

    Intersection Observer: react when elements scroll into view

    Scroll listeners that measure element positions are slow and fiddly. Intersection Observer tells you when an element enters the viewport, with a few lines of code.

Tell us what’s in the way.

A few lines is enough. You get a candid yes, a candid no, or a sharper question.

  • Working software in week four
  • A reply in one business day
  • Handover is the deliverable

Prefer email? [email protected]

The problem, who it is for, and what is in the way right now.

One business day to a real reply. No sales sequence, no call required.