Recently I was looking at some backend code in express, and I found an interesting pattern of using await Promise.all()
.
We’re all very familiar with async await
. So how about Promise.all? Based on MDN, the Promise.all()
method takes an iterable of promises as an input, and returns a single Promise
as an output. This returned promise will resolve when all of the input's promises have resolved and non-promises have returned, or if the input iterable contains no promises. And not surprisingly, it rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.
A classic use case:
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, ‘foo’);
});Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, “foo”]
So how is it combined with async/await?
Well while async/await is good to use, you might have situations where you have a list of await keywords queuing on the pipeline:
async function(){...
await functionA()
await functionB()
await functionC()
...}
So let’s assume function A, B, C each takes 1,2,3 sec to run, then the above code will take 1+2+3 = 6 sec to run. It’s quite a waste of time, when your cores can potentially take 2~8 tasks in parallel.
So that’s how Promise.all()
comes to rescue.
Since it takes “an iterable of promises” as an input, it means we can run several functions in parallel, and pass in the result as promise as the parameter. Consider experiments below:
(async () => {
const time1= await Promise.delay(500); //takes 500ms to run
const time2 = await Promise.delay(300); //waits for 500ms then run
const time3 = await Promise.delay(200); //waits for 3000ms then run
})();
The total running time will be 1s. How about below:
(async () => {
await Promise.all([
Promise.delay(500),
Promise.delay(300),
Promise.delay(200]); //runs simultaneously
})();
Guess how long the above code takes to run? 500ms! The 2nd and 3rd promise will be finishing each 200ms and 300ms earlier respectively. But because the first will take 500ms, that determines the final time to run.
As you can see, when used properly, await Promise.all()
can improve the code performance significantly.
Hope you enjoy this short post! Happy reading!