DevPath · Learn to code ESPTEN

Asynchrony: promises and async/await

Promise combinators

Four ways to combine promises

When you have several promises at once, you rarely want to await them one by one. The Promise class offers four static methods that take an array (iterable) of promises and return a single promise that coordinates them.

Promise.all — "all or nothing"

It launches them all in parallel and fulfills with an array of results (in the same order) when all of them fulfill. If a single one rejects, all rejects immediately with that error (the rest keep running, but their result is ignored).

const [user, orders] = await Promise.all([requestUser(), requestOrders()]);

Use it when you need all the results and the failure of any one invalidates the set. It's like a menu: if a dish is missing, you don't serve the meal.

Promise.allSettled — "tell me how each one did"

It waits for all of them to finish (whether they fulfill or reject) and never rejects. It returns an array of objects with the state of each one:

const results = await Promise.allSettled([requestA(), requestB()]);
const successes = results.filter((r) => r.status === "fulfilled");

Use it when you want to try everything and then review the outcome, without an isolated failure ruining the rest (sending 100 emails, uploading several files...).

Promise.race — "the first one to finish, win or lose"

It resolves or rejects with the first promise that changes state, whether fulfilled or rejected.

const winner = await Promise.race([requestData(), timeLimit(5000)]);

A classic for setting a timeout: you race your request against a timer that rejects; whoever wins, you don't end up waiting forever.

Promise.any — "the first one to SUCCEED"

It fulfills with the first one to fulfill and ignores rejections. It only rejects if all of them fail (with an AggregateError that groups the errors).

const fastest = await Promise.any([server1(), server2(), server3()]);

Use it when you have several equivalent sources and the first one that responds well is enough (server replicas, download mirrors...).

Quick summary

Method Fulfills when... Rejects when...
all all fulfill the first one rejects
allSettled all finish never
race the first finishes (success) the first finishes (failure)
any the first one fulfills all reject

Examples

all parallelizes and returns an ordered array

async function demo() {
  const results = await Promise.all([
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3),
  ]);
  console.log(results); // [1, 2, 3]
}
demo();

allSettled never rejects: it gives you the outcome

async function demo() {
  const r = await Promise.allSettled([
    Promise.resolve("ok"),
    Promise.reject(new Error("failed")),
  ]);
  console.log(r[0].status, "/", r[1].status); // fulfilled / rejected
}
demo();

any keeps the first one that succeeds

async function demo() {
  const value = await Promise.any([
    Promise.reject(new Error("slow")),
    Promise.resolve("fast"),
  ]);
  console.log(value); // "fast"
}
demo();
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Microtasks vs macrotasksAsynchronous errors →