DEV Community

Cover image for How to call async/await functions in parallel
collegewap
collegewap

Posted on • Originally published at codingdeft.com

How to call async/await functions in parallel

Consider the following code:

const p1 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo")
    }, 1000)
  })

const p2 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("bar")
    }, 1000)
  })
Enter fullscreen mode Exit fullscreen mode

We have 2 functions, which return a promise. Both the promises will resolve after 1 second. This is how we can mock async calls.

If we call the promises one after the other so that we can process the results together, as shown below,

const runSerial = async () => {
  console.time("runSerial")
  try {
    const r1 = await p1()
    const r2 = await p2()
    console.log([r1, r2]) //πŸ‘‰ [ 'foo', 'bar' ]
  } catch (error) {
    console.log(error)
  }
  console.timeEnd("runSerial") //πŸ‘‰ runSerial: 2.031s
}
runSerial()
Enter fullscreen mode Exit fullscreen mode

The second promise will wait until the first one is resolved, then only the second function will be called.
This will result in a total execution time of at least 2 seconds.

So to reduce the turnaround time and still have all the results in one place, we can run them in parallel using Promise.all() and Promise.allSettled().

Using Promise.all()

We can use Promise.all as shown below:

const p1 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo")
    }, 1000)
  })

const p2 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("bar")
    }, 1000)
  })

const runParallelAll = async () => {
  console.time("runParallelAll")

  try {
    const p = await Promise.all([p1(), p2()])
    console.log(p) //πŸ‘‰ [ 'foo', 'bar' ]
  } catch (error) {
    console.log(error)
  }
  console.timeEnd("runParallelAll") //πŸ‘‰ runParallelAll: 1.026s
}
runParallelAll()
Enter fullscreen mode Exit fullscreen mode

Now both calls will happen in parallel and the total time taken to resolve all the promises is the total time taken by the slowest promise.

The problem with Promise.all is, it will throw error if any one of the promises rejects.

const p1 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo")
    }, 1000)
  })

const p2 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("bar")
    }, 1000)
  })

const runParallelAll = async () => {
  console.time("runParallelAll")

  try {
    const p = await Promise.all([p1(), p2()])
    console.log(p)
  } catch (error) {
    console.log(error) // πŸ‘‰ bar
  }
  console.timeEnd("runParallelAll")
}
runParallelAll()
Enter fullscreen mode Exit fullscreen mode

As you can see in the above code, when a promise gets rejected, it will be caught and the rejected reason will be logged.

Using Promise.allSettled()

If you want the promise to be resolved even if any promises called in parallel get rejected, then you can use Promise.allSettled.

const p1 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo")
    }, 1000)
  })

const p2 = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("bar")
    }, 1000)
  })

const runParallelAllSettled = async () => {
  console.time("runParallelAllSettled")

  try {
    const p = await Promise.allSettled([p1(), p2()])
    console.log(p) //πŸ‘‰ [{"status":"fulfilled","value":"foo"},{"status":"fulfilled","value":"bar"}]
  } catch (error) {
    console.log(error)
  }
  console.timeEnd("runParallelAllSettled") //πŸ‘‰ runParallelAllSettled: 1.014s
}
runParallelAllSettled()
Enter fullscreen mode Exit fullscreen mode

Now you can loop through the following response and check which promise has been resolved and which has been rejected.

[
  { "status": "fulfilled", "value": "foo" },
  { "status": "fulfilled", "value": "bar" }
]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)