Boldizsár's programming blog

Wait for all promises to complete even when some reject

June 21, 2019 | 3 Minute Read

Promise.all fails when one of the promises fail. Let's see how to prevent this

If you have some promises and you want all of them to complete before you move on you can use Promise.all. It takes an array of promises and resolves if all of them have resolved. But the sometimes annoying part is that even if just one rejects Promise.all rejects too. Let’s say you’re making API requests for example downloading a bunch of articles and you want to show them to the user on your blog. In JavaScript we wrap our API requests into promises since this is how we work with asynchronous actions. Promise.all is a built in JavaScript API which we use to wait for all the promises to complete. But if one of them fails then the whole promise fails which is not something I often times want. Let’s see an example.

const p1 = Promise.resolve(5);
const p2 = Promise.reject(new Error('rejected'));
const p3 = new Promise((res, rej) => {
  setTimeout(() => {
    res('Success');
  }, 1000)
});

Promise.all([p1, p2, p3])
  .then(values => {
    console.log(values)
  })
  .catch(error => {
    console.error(error)
  })

And the result is

Error: rejected

Not much right? Even two from our three promises resolved successfully we see an error but we have no clue which one. It might be your use case that you want this behaviour from Promise.all but what if you want it to be resolved even if one of them fails. Let’s see how we can do that.

const p1 = Promise.resolve(5);
const p2 = Promise.reject(new Error('rejected'));
const p3 = new Promise((res, rej) => {
  setTimeout(() => {
    res('Success');
  }, 1000)
});

const promises = [p1, p2, p3].map(p => p.catch(e => e));

Promise.all(promises)
  .then(values => {
    console.log(values)
  })
  .catch(error => {
    console.error(error)
  })

We can see the following result

[5, Error, "Success"]

What I’m doing here is basically appending a rejection handler callback to each promise. In this rejection handler I’m returning the Error object which is the reason why the promise failed. Returning from the catch internally calls then so this is why returning the Error object is like resolving with an error. So now values is an array and it will contain our Error object too. We now know that our second promise failed and we’re still able to see the resolved values of the other promises. Pretty cool I think.

Thanks for reading my article, see you in the next one.