How to call async/await functions in parallel
Tags: javascript, api
Published: 2023-04-08 10:26:20


Consider the following code:

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

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

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,

```js
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()
```

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()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) and [Promise.allSettled()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled).

## Using Promise.all()

We can use `Promise.all` as shown below:

```js
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()
```

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.

```js
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()
```

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`.

```js
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()
```

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

```json
[
  { "status": "fulfilled", "value": "foo" },
  { "status": "fulfilled", "value": "bar" }
]
```