Table of Contents
Consider the following code:
1const p1 = () =>2 new Promise((resolve, reject) => {3 setTimeout(() => {4 resolve("foo")5 }, 1000)6 })78const 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.031s11}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 })78const p2 = () =>9 new Promise((resolve, reject) => {10 setTimeout(() => {11 resolve("bar")12 }, 1000)13 })1415const runParallelAll = async () => {16 console.time("runParallelAll")1718 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.026s25}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 })78const p2 = () =>9 new Promise((resolve, reject) => {10 setTimeout(() => {11 reject("bar")12 }, 1000)13 })1415const runParallelAll = async () => {16 console.time("runParallelAll")1718 try {19 const p = await Promise.all([p1(), p2()])20 console.log(p)21 } catch (error) {22 console.log(error) // 👉 bar23 }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 })78const p2 = () =>9 new Promise((resolve, reject) => {10 setTimeout(() => {11 reject("bar")12 }, 1000)13 })1415const runParallelAllSettled = async () => {16 console.time("runParallelAllSettled")1718 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.014s25}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!
Leave a Comment