TypeOfNaN

What is the Difference Between Promise.all and Promise.allSettled?

Nick Scialli
May 13, 2021

Promise.all and Promise.allSettled are two different ways to handle an array of Promises in JavaScript. Let’s compare them and talk about when it might be appropriate to use each.

How They’re Similar

The primary similarity between Promise.all and Promise.allSettled is that both methods take an array of Promises as an argument. You use them because you have a group of Promises that you want to handle before moving on. That’s kind of where the similarities end though. As we’ll see, the ways these methods actually handle Promises are quite different.

The Big Difference: Handling Rejection(s)

Handling rejection is the big differentiator between Promise.all and Promise.allSettled. If you want your group of Promise to fail immediately as soon as one of the Promises is rejected, you should use Promise.all. However, if you want to give all Promises a shot before moving on, consider Promise.allSettled.

Let’s take the following example of a function that returns a Promise that has a 50/50 chance of resolving or rejecting and will do so after a random amount of time.

function randomPromise(id) {
  return new Promise(function (res, rej) {
    setTimeout(function () {
      if (Math.random() > 0.5) {
        res(id);
      } else {
        rej(`${id} failed randomly!`);
      }
    }, Math.random() * 1000);
  });
}

Promise.all

When handling rejection, Promise.all is all or nothing. If one Promise rejects, Promise.all immediately stops and calls the catch method with the reported error.

Promise.all([randomPromise(1), randomPromise(2), randomPromise(3)])
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err);
  });

If all three Promises successfully resolve, you’ll see [1, 2, 3] logged to the console. More likely, however, is that one of the Promises fails. As soon as it does you will see the error for that Promise printed to the console:

2 failed randomly!

Note a couple things:

  • Even though the first and third Promise might have resolved successfully, we never make it to the then method, we just went straight to catch.
  • You will never see two errors in the console because Promise.all fails immediately when one of the Promises rejects.

Promise.allSettled

Promise.allSettled will go ahead and let all Promise resolve or reject (i.e., settle) before giving you the results. Promise.allSettled doesn’t reject and it gives you all the information you need in the then method.

Let’s look at the previous example and you’ll see what I mean:

Promise.allSettled([randomPromise(1), randomPromise(2), randomPromise(3)]).then(
  function (data) {
    console.log(data);
  }
);

If all three Promises resolve successfully, the data logged to the console will look like this:

[
  { status: "fulfilled", value: 1 },
  { status: "fulfilled", value: 2 },
  { status: "fulfilled", value: 3 }
]

Not that we now get status information in our then handler. Why is that? Well, it’s because if any number of the Promises rejects, you need to know that information. With allSettled, we can have Promises in the array reject and we’ll still wait for the rest of the Promises to resolve (or reject) before moving on to the then handler, at which point we get information about all the Promises (even the rejected ones).

Let’s look at an example where two of the Promises rejected. Our data logged to the console might look like this:

[
  { status: "rejected", reason: "1 failed randomly!" },
  { status: "fulfilled", value: 2 },
  { status: "rejected", reason: "3 failed randomly!" }
]

Conclusion

If your Promises are related such that you’d like to immediately bail when one of the Promises rejects, Promise.all is probably for you. However, if you’d like to keep going with the rest of the Promises even if any number of them fail, then you should probably reach for Promise.allSettled.

Nick Scialli

Nick Scialli is a senior UI engineer at Microsoft.

© 2024 Nick Scialli