Promise.all() and parallel promises are they differ in node

I have a scenario where I can implement my code to make axios requests in two ways

1st way

const data = {};

try {

  if (searchArray.includes('address')) {
    const address = await axios('./getAddress')
    data.addresses = address.data;
  }

  if (searchArray.includes('email')) {
    const email = await axios('./email')
    data.emails = email.data;
  }

  if (searchArray.includes('phone')) {
    const phoneNumber = await axios('./phone')
    data.phoneNumbers = phoneNumber.data;

  }
} catch (err) {
  return res.status(constants.HTTP_SERVER_ERROR).json(err);
}

res.status(200).json(data);

2nd Way

const data = {};
const promises = []

if (searchArray.includes('address')) {
  promises.push(axios('./getAddress'))
}

if (searchArray.includes('email')) {
  promises.push(axios('./email'))
}

if (searchArray.includes('phone')) {
  promises.push(axios('./phone'))
}

Promise.all(promises)
  .then(results => {
    res.status(200).json(results);
  })
  .catch(err) {
    return res.status(constants.HTTP_SERVER_ERROR).json(err);
  }

Which is the better approach? and why?

I prefer 1st approach because I can have well structured data than complete array of results. But got suggestion to implement sequentially than parallel

I assume node is single threaded so didn't find any difference in implementing it (I might be wrong if I use async and await)

2 answers

  • answered 2018-10-11 19:12 doublesharp

    The second approach will be more performant.

    In the first example assume that each request takes 1 second to return, so you will take at least 3+ seconds to return your results as you wait for the result of one request before making the next.

    In the second approach you make all the requests at once, and then wait for the IO callback. Once all the requests are handled the Promise.all() will resolve. If each request takes ~1 sec but is made in parallel your response will be about 1 second as well.

    I would use syntax like the following however to maintain readability as you seem to be using async/await and don't need to have a reference to the promises.

    try {
      const [addresses, emails, phones] = await Promise.all([
        searchArray.includes('address') 
          ? axios('./getAddress') : Promise.resolve({}),
        searchArray.includes('email') 
          ? axios('./email') : Promise.resolve({}),
        searchArray.includes('phone') 
          ? axios('./phone') : Promise.resolve({}),
      ]);
      return res.status(200).json({
         addresses: addresses.data,
         emails: emails.data,
         phoneNumbers: phones.data,
      });
    } catch (err) {
      return res.status(constants.HTTP_SERVER_ERROR).json(err);
    }
    

  • answered 2018-10-11 19:19 binariedMe

    The statement "Javascript is single threaded" often confuses people.

    While the main thread of code execution is single threaded, async executions are not usually handled by main thread. So basically when you execute few async tasks in series vs parallel, parallel execution is going to be faster for sure.

    We go for async await approach sometimes if we need to wrap a number of dependent async operations in a single promise. Independent async operations should be executed in parallel.