Categories
JavaScript Answers

How to Wait Until All Promises Complete Even If Some Are Rejected?

Spread the love

Sometimes, we may want to wait until all promises to complete but we may want to proceed regardless of whether some promises are rejected or not.

In this article, we’ll look at how to wait until all promises are completed even if some are rejected.

Promise.allSettled

The Promise.allSettled method lets us proceed with running the then callback regardless of whether all promises are complete.

For instance, we can write:

Promise.allSettled([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(3),
]).then(([result1, result2, result3]) => {
  console.log(result1, result2, result3)
});

Then result1 is {status: “fulfilled”, value: 1} .

result2 is {status: “fulfilled”, value: 2} .

And result3 is {status: “rejected”, reason: 3} .

status has the status of each promise.

And value has the resolved value if the promise is resolved.

And reason has the rejected value if the promise is rejected.

We can also write the same code with the async and await syntax.

For instance, we can write:

(async () => {
  const [result1, result2, result3] = await Promise.allSettled([
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.reject(3),
  ])
  console.log(result1, result2, result3)
})()

And we get the same values as before for result1 , result2 , and result3 .

Promise.all with map

We can call map on the promise array.

Then we pass in a callback that calls catch on any promise that are rejected.

The catch callback only runs when a promise is rejected, so we either return the promise itself if catch isn’t run.

Otherwise, we return a promise with the catch callback run.

So we can write:

Promise.all(
    [
      Promise.resolve(1),
      Promise.resolve(2),
      Promise.reject(3),
    ]
    .map(p => p.catch(e => e))
  )
  .then(([result1, result2, result3]) => {
    console.log(result1, result2, result3)
  });

We call map with p => p.catch(e => e) to return any promises that are rejected with a promise that’s caught.

In the catch callback, we return the rejection reason.

Then in the then callback, we can destructure the promise results as usual.

So we get that result1 is 1.

result2 is 2.

And result3 is 3.

We can write tyhe same code with async and await by writing:

(async () => {
  const [result1, result2, result3] = await Promise.all([
      Promise.resolve(1),
      Promise.resolve(2),
      Promise.reject(3),
    ]
    .map(p => p.catch(e => e))
  )
  console.log(result1, result2, result3)
})()

And we get the same result as before.

Conclusion

The Promise.allSettled method is the best way to run code after a promise is run regardless of the outcomes of the promises that are run.

If we don’t want to use that, we can also use Promise.all with map and catch .

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *