Managing the State of Your Promises

Without using anything elaborate like a React, Redux state manager or global variables, what if there was another way of keeping track of the state of all Promises?

Promise.all

Normally, I use Promise.all to input all my promises to run them in parallel, but if any of those promises failed, then this bundled promise would immediately reject with the error of the first failed promise.

For example, if I input promises like this:


async function promiseAllRejectData() {
  const result = await Promise.all([
    fetch("https://yesno.wtf/api"),
    new Promise((_, reject) => reject(new Error("❌ Rejected"))),
  ]);

  return result;
}

Then my return will would look something like this: “Error: ❌ Rejected”

Promise.all is great when you want to run several promises and continue only when all of them succeed. However, sometimes I want to run several promises and know the outcome of each one and not just stop at the first failure. In that case, I highly recommend using Promise.allSettled.

Promise.allSettled

This JavaScript method allows you to concurrently run all inputed promises and return an array with the status for each promise, whether it was resolved or not.

For example:


async function promiseAllSettledData() {
  return await Promise.allSettled([
    fetch("https://httpbin.org/bytes/11"),
    fetch("https://httpbin.org/robots.txt"),
    new Promise((_, reject) => reject(new Error("❌ Rejected"))),
  ]);
}

Something like this function would return:


[
   {status: 'fulfilled', value: Response1},
   {status: 'fulfilled', value: Response2},
   {status: 'rejected', reason: Error("❌ Rejected")}
]

Now, I always get the result of each promise no matter what.

Use Case

A cool case I ended using this for was when I needed a few promises to resolve or immediately fail in separate occasions and see the result of each occasion.

For example, in scenario 1, I would have 2 promises run and in scenario 2 I would run promiseAllRejectData (mentioned above). Then, know the result of both scenarios at the end.


async function promiseAllData() {
  const [yesNoResponse, dadJokeResponse] = await Promise.all([
    fetch("https://yesno.wtf/api"),
    fetch("https://icanhazdadjoke.com/", {
      headers: {
        Accept: "application/json",
      },
    }),
  ]);

  const yesNo = await yesNoResponse.json();
  const dadJoke = await dadJokeResponse.json();

  return { yesNo, dadJoke };
}

async function promiseAllSettledData() {
  return await Promise.allSettled([promiseAllData(), promiseAllRejectData()]);
}

promiseAllSettledData().then((result) => {
  console.log(result);
});

Now I have two functions that will need to resolve before promiseAllSettledData is processed. Afterwards, I’m able to see an array that shows that promiseAllData‘s status is “fulfilled” and promiseAllRejectData‘s status is “rejected.”

Final Note

Promise.all plus Promise.allSettled has given me more flexibility to track async state. Knowing that there is a method out there that will return the status of all promises has definitely been a great alternative to using some other complex state management tools.

Conversation

Join the conversation

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