Catch errors in Promise.all

A safe alternative to Javascript's Promise.all

Awaiting all promises including errors

If you’re a Javascript-developer, you’ve most likely used the standard built-in object Promise and its API Promise.all, which awaits until all promises provided in an array have resolved. This is a very elegant way to await various asynchronous results before proceeding with your business logic.

But this API doesn’t handle errors. Whenever at least one error occurs in the array of promises, the function stops immediately and no further results are awaited.

Promise.allSettled awaits all async results

Luckily there’s a second API called Promise.allSettled available that guarantees to await all promises, no matter if the result is valid or an error. The following code demonstrates its usage, which is really simple, but can save you a lot of headache.

The main difference to Promise.all is that each promise gets resolved to a tuple of information, where both the state (fulfilled or rejected) as well as the value (in case of fulfilled) or the reason (in case of rejected) are available.

Providing an empty array

A special case you should be aware of is that when Promise.allSettled receives an empty array as input, it immediatly resovles to an empty array. This sounds logical and is the expected behavior, but I still wanted to point it out.

/**
 * A simple dummy function that
 * fetches data from multiple
 * endpoints related to a user.
 */
async function fetchUserData(id){
  // A simple array of promises.
  // The first two parameters are
  // mock calls from down below.
  const promises = [
    fetchUserHistory(id),
    fetchUserProfile(id),
    // For testing only, let's throw.
    Promise.reject(new Error('an error'))
];
  
  const values = await Promise.allSettled(promises);
  // values === [
  //    { status: "fulfilled", value: [1, 2, 3] },
  //    { status: "fulfilled", value: {name:"dummy"} },
  //    { status: "rejected", reason: {}
  // ]
}

// The following functions are just mocks
// and should help improve readability
// of the example at the top.

async function fetchUserHistory(id){
  return Promise.resolve([1,2,3]);
}

async function fetchUserProfile(id){
  return Promise.resolve({ name: "dummy" });
}

As you can see, Promise.allSettled is a very nice addition to Promise.all and allows you to await all results, independent of their results. I don’t think that this API will fit every use case, but it sure saves your from wrapping async calls in an overhead try-catch-block.

Suggestions

Related

Addendum

Languages