Using async-await in array iteration methods [JS]⌚

You are new to the javascript world, and you just found out the simplicity of using array iterations and the clean look they provide. Now, you start async-await in conjunction with array iteration methods, and all of a sudden you start to notice that the result it gives isn't the one you are looking for. Look at the example below

const { default: Axios } = require('axios');

const urls = ['https://supercharged.dev', 'https://blog.supercharged.dev'];

const getUrlStatus = async () => {
  const statuses = await urls.map(async (item) => {
    const urlResponse = await Axios.get(item);
    return urlResponse.status;
  });
  return statuses;
};

const main = async () => {
  console.log(await getUrlStatus());
};

main();

When you run the above example you expect it to provide the status returned by the URL's, but you get the following result

[ Promise { <pending> }, Promise { <pending> } ]

The problem here is we are awaiting an array of promises rather than the promise. To fix this all we have to do is use Promise.all function.

The Promise.all() method takes an iterable of promises as an input and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error and will reject with this first rejection message/error. MDN docs

So after making changes to the example above we have

const { default: Axios } = require('axios');

const urls = ['https://supercharged.dev', 'https://blog.supercharged.dev'];

const getUrlStatus = async () => {
  const statuses = await Promise.all(
    urls.map(async (item) => {
      const urlResponse = await Axios.get(item);
      return urlResponse.status;
    })
  );
  return statuses;
};

const main = async () => {
  console.log(await getUrlStatus());
};

main();

And the response is.... (Drumroll 🥁)

[ 200, 200 ]

If you want to allow failures in promise.all you can use the below snippet

const getUrlStatus = async () => {
  let statuses = urls.map(async (item) => {
    const urlResponse = await Axios.get(item);
    return urlResponse.status;
  });
  statuses = await Promise.all(
    statuses.map((promise) => promise.catch((err) => null))
  );
  return statuses;
};

you will get a null for the promises that failed.

No Comments Yet