I have already gone through the thread Any difference between await Promise.all() and multiple await?, so I am clear about Promise.all and multiple awaits.
Still, I am not very clear about the below 2 scenarios.
In Case 1 why does it execute sequentially (takes 10s) whereas in Case 2 it executes in parallel (takes 4s)?
Case 1:
function promiseWait(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
}, time);
});
}
async function test1() {
var t0 = performance.now()
var a = await promiseWait(1000)
var b = await promiseWait(2000)
var c = await promiseWait(3000)
var d = await promiseWait(4000)
var t1 = performance.now()
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds."); //takes 10secs
}
test1()
Case 2:
function promiseWait(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
}, time);
});
}
async function test2() {
var t0 = performance.now()
const p1 = promiseWait(1000);
const p2 = promiseWait(2000);
const p3 = promiseWait(3000);
const p4 = promiseWait(4000);
const a = await p1;
const b = await p2;
const c = await p3;
const d = await p4;
var t1 = performance.now()
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")
}
test2()
In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() .
javascript - async / await run async functions sequentially in nodejs, puppeteer - Stack Overflow.
Await basically waits for the results which are particularly to be fetched from the source from which that async function is about to fetch the data. Await takes a little time to fetch the results from the source (like API) and thereafter along with the async function returns the result in the form of a promise.
Async Await Promisesawait syntax in ES6 offers a new way write more readable and scalable code to handle promises. It uses the same features that were already built into JavaScript.
In the first case because of the await
before each call to the promiseWait
, to even start executing the next call to the promiseWait
it needs to wait until the first call to the promiseWait
is finished completely. So you see sequential execution.
In the second case you have already invoked all the promiseWait
functions before you start awaiting them. So the promiseWait
has already started executing, then you are awaiting the results one after another.
Implementation wise in the first scenario, the next call to the setTimeout
has to wait until the first setTimeout
expires. So the second, third and the fourth timers need to wait until the first timer expires and resolves the promise in order to be scheduled.
In the seconds case you schedule the setTimeout
calls one after the other, so the timers are all already queued. Then you are just awaiting for the timers to expire and resolve your promise one by one.
With some more deep dive ... (Inspired by Philip Roberts).
Case 1: SetTimeout triggers one by one
function promiseWait(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new Date().toISOString().split('.')[0].replace('T',' '));
}, time);
});
}
async function test1() {
let timeStamp = new Date();
var t0 = new Date();
console.log("t0",t0)
var a = await promiseWait(1000)
console.log("a",a)
var b = await promiseWait(2000)
console.log("b",b)
var c = await promiseWait(3000)
console.log("c",c)
var d = await promiseWait(4000)
console.log("d",d)
var t1 = new Date();
console.log("t1",t1)
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds."); //takes 10secs
}
test1()
Console: You can notice that sum of each timeout is resulted ~10 Secs.
Case 2: SetTimeout triggers at same time.
function promiseWait(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new Date().toISOString().split('.')[0].replace('T',' '));
}, time);
});
}
async function test1() {
let timeStamp = new Date();
var t0 = new Date();
console.log("t0",t0)
const p1 = promiseWait(1000);
const p2 = promiseWait(2000);
const p3 = promiseWait(3000);
const p4 = promiseWait(4000);
console.log("p1",p1);
console.log("p2",p2);
console.log("p3",p3);
console.log("p4",p4);
const a = await p1;
console.log("a",a);
const b = await p2;
console.log("b",b);
const c = await p3;
console.log("c",c);
const d = await p4;
console.log("d",d);
var t1 = new Date();
console.log("t1",t1)
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds."); //takes 10secs
}
test1()
Console: Here we can notice that timer started together so it resulted with ~ 4 Secs. (Last timer is set at 4 sec).
I this case all 4 promises started at the same time. Therefore its setTimeout timer runs parallel in the background.
The timers have an difference with 1 second so if you put an console log between the awaits you should see around every second a new console log.
function promiseWait(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
}, time);
});
}
async function test2() {
var t0 = performance.now()
console.log("putting promises in que");
const p1 = promiseWait(1000);
const p2 = promiseWait(2000);
const p3 = promiseWait(3000);
const p4 = promiseWait(4000);
console.log("promises where added to the que");
const a = await p1;
console.log("1")
const b = await p2;
console.log("2")
const c = await p3;
console.log("3")
const d = await p4;
console.log("4")
var t1 = performance.now()
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")
}
test2()
Visualized it looks something like this:
setTimeout(() => {
let divs = document.querySelectorAll("div").forEach(div => {
div.style.setProperty("width", "100%")
})
},500)
div {
height: 30px;
background: red;
margin: 10px;
width: 0px;
transition: width 4s;
color: white
}
<div style="max-width: 100px";>
Promise 1
</div>
<div style="max-width: 200px";>
Promise 2
</div>
<div style="max-width: 300px";>
Promise 3
</div>
<div style="max-width: 400px";>
Promise 4
</div>
Case 1 visualized:
let divs = document.querySelectorAll("div")
let delay = (time) => new Promise(res => setTimeout(res, time));
(async() => {
for(let i = 0; i < divs.length; i++) {
await delay(i + 1000);
divs[i].style.setProperty("width", "100%");
}
})()
div {
height: 30px;
background: red;
margin: 10px;
width: 0px;
transition: width 4s;
color: white
}
<div style="max-width: 100px";>
Promise 1
</div>
<div style="max-width: 200px";>
Promise 2
</div>
<div style="max-width: 300px";>
Promise 3
</div>
<div style="max-width: 400px";>
Promise 4
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With