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. Code Snippets4 min read

    Simplify Promise Handling with Promise.withResolvers

    Learn how the new Promise.withResolvers static method streamlines common asynchronous patterns in JavaScript, reducing boilerplate and improving code clarity.

  2. 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.

  3. Code Snippets4 min read

    Simplify Popups with HTML Popover API

    Learn how to effortlessly create accessible popups, tooltips, and modals using the native HTML Popover API, reducing custom JavaScript and improving user experience.

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? hello@2haas.com

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.