Skip to content
javascript

How to call async/await functions in parallel

Feb 14, 2023Abhishek EH3 Min Read
How to call async/await functions in parallel

Consider the following code:

1const p1 = () =>
2 new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve("foo")
5 }, 1000)
6 })
7
8const p2 = () =>
9 new Promise((resolve, reject) => {
10 setTimeout(() => {
11 resolve("bar")
12 }, 1000)
13 })

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,

1const runSerial = async () => {
2 console.time("runSerial")
3 try {
4 const r1 = await p1()
5 const r2 = await p2()
6 console.log([r1, r2]) //👉 [ 'foo', 'bar' ]
7 } catch (error) {
8 console.log(error)
9 }
10 console.timeEnd("runSerial") //👉 runSerial: 2.031s
11}
12runSerial()

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:

1const p1 = () =>
2 new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve("foo")
5 }, 1000)
6 })
7
8const p2 = () =>
9 new Promise((resolve, reject) => {
10 setTimeout(() => {
11 resolve("bar")
12 }, 1000)
13 })
14
15const runParallelAll = async () => {
16 console.time("runParallelAll")
17
18 try {
19 const p = await Promise.all([p1(), p2()])
20 console.log(p) //👉 [ 'foo', 'bar' ]
21 } catch (error) {
22 console.log(error)
23 }
24 console.timeEnd("runParallelAll") //👉 runParallelAll: 1.026s
25}
26runParallelAll()

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.

1const p1 = () =>
2 new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve("foo")
5 }, 1000)
6 })
7
8const p2 = () =>
9 new Promise((resolve, reject) => {
10 setTimeout(() => {
11 reject("bar")
12 }, 1000)
13 })
14
15const runParallelAll = async () => {
16 console.time("runParallelAll")
17
18 try {
19 const p = await Promise.all([p1(), p2()])
20 console.log(p)
21 } catch (error) {
22 console.log(error) // 👉 bar
23 }
24 console.timeEnd("runParallelAll")
25}
26runParallelAll()

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.

1const p1 = () =>
2 new Promise((resolve, reject) => {
3 setTimeout(() => {
4 resolve("foo")
5 }, 1000)
6 })
7
8const p2 = () =>
9 new Promise((resolve, reject) => {
10 setTimeout(() => {
11 reject("bar")
12 }, 1000)
13 })
14
15const runParallelAllSettled = async () => {
16 console.time("runParallelAllSettled")
17
18 try {
19 const p = await Promise.allSettled([p1(), p2()])
20 console.log(p) //👉 [{"status":"fulfilled","value":"foo"},{"status":"fulfilled","value":"bar"}]
21 } catch (error) {
22 console.log(error)
23 }
24 console.timeEnd("runParallelAllSettled") //👉 runParallelAllSettled: 1.014s
25}
26runParallelAllSettled()

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

1[
2 { "status": "fulfilled", "value": "foo" },
3 { "status": "fulfilled", "value": "bar" }
4]

Do follow me on twitter where I post developer insights more often!

Related Articles

Leave a Comment

© 2024 CodingDeft.Com