Consider the following code:
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,
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() 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()
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()
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()
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" }
]
Top comments (0)