Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
143 lines (114 sloc) 5.78 KB
title author avatars date tags description tweet
Promise combinators
Mathias Bynens ([@mathias](
There are four promise combinators in JavaScript: Promise.all, Promise.race, Promise.allSettled, and Promise.any.

Since the introduction of promises in ES2015, JavaScript has supported exactly two promise combinators: the static methods Promise.all and Promise.race.

Two new proposals are currently making their way through the standardization process: Promise.allSettled, and Promise.any. With those additions, there’ll be a total of four promise combinators in JavaScript, each enabling different use cases.

Here’s an overview of the four combinators:

:::table-wrapper | name | description | status | | ------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------- | | Promise.allSettled | does not short-circuit | proposal | | Promise.all | short-circuits when an input value is rejected | added in ES2015 | | Promise.race | short-circuits when an input value is settled | added in ES2015 | | Promise.any | short-circuits when an input value is fulfilled | proposal | :::

Let’s take a look at an example use case for each combinator.


Promise.all lets you know when either all input promises have fulfilled or when one of them rejects.

Imagine the user clicks a button and you want to load some stylesheets so you can render a completely new UI. This program kicks off an HTTP request for each stylesheet in parallel:

const promises = [
try {
  const styleResponses = await Promise.all(promises);
} catch (reason) {

You only want to start rendering the new UI once all requests succeeded. If something goes wrong, you want to instead display an error message as soon as possible, without waiting for other any other work to finish.

In such a case, you could use Promise.all: you want to know when all promises are fulfilled, or as soon as one of them rejects.


Promise.race is useful if you want to run multiple promises, and either…

  1. do something with the first successful result that comes in (in case one of the promises fulfills), or
  2. do something as soon as one of the promises rejects.

That is, if one of the promises rejects, you want to preserve that rejection to treat the error case separately. The following example does exactly that:

try {
  const result = await Promise.race([
} catch (error) {

We kick off a computationally expensive task that might take a long time, but we race it against a promise that rejects after 2 seconds. Depending on the first promise to fulfill or reject, we either render the computed result, or the error message, in two separate code paths.


Promise.allSettled gives you a signal when all the input promises are settled, which means they’re either fulfilled or rejected. This is useful in cases where you don’t care about the state of the promise, you just want to know when the work is done, regardless of whether it was successful.

For example, you can kick off a series of independent API calls and use Promise.allSettled to make sure they’re all completed before doing something else, like removing a loading spinner:

const promises = [
// Imagine some of these requests fail, and some succeed.

await Promise.allSettled(promises);
// All API calls have finished (either failed or succeeded).


Promise.any gives you a signal as soon as one of the promises fulfills. This is similar to Promise.race, except any doesn’t reject early when one of the promises rejects.

const promises = [
  fetch('/endpoint-a').then(() => 'a'),
  fetch('/endpoint-b').then(() => 'b'),
  fetch('/endpoint-c').then(() => 'c'),
try {
  const first = await Promise.any(promises);
  // Any of the promises was fulfilled.
  // → e.g. 'b'
} catch (error) {
  // All of the promises were rejected.

This code example checks which endpoint responds the fastest, and then logs it. Only if all of the requests fail do we end up in the catch block, where we can then handle the errors.

You can’t perform that action at this time.