I thought I understood how the async/await works in Javascript until I ran the code:
let flag = false;
function test() {
[1, 2, 3].map(async n => {
console.log(`flag set at ${n} before if?`, flag);
if (!flag) {
const x = await a(n);
// do something with x
flag = x;
console.log('flag set!');
}
console.log(`flag set at ${n} after if?`, flag);
});
}
function a(n) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(n);
});
});
}
test();
The actual output is:
flag set at 1 before if? false
flag set at 2 before if? false
flag set at 3 before if? false
flag set!
flag set at 1 after if? 1
flag set!
flag set at 2 after if? 2
flag set!
flag set at 3 after if? 3
Which is very different from what I thought it should be:
flag set at 1 before if? false
flag set!
flag set at 1 after if? 1
flag set at 2 before if? 1
flag set at 2 after if? 1
flag set at 3 before if? 1
flag set at 3 after if? 1
I think I need to be educated. Thanks.
Update: Thanks for the comments mentioning about the map. When I changed my code to be the following, it worked as expected:
let flag = false;
async function test() {
for (const n of [1, 2, 3]) {
console.log(`flag set at ${n} before if?`, flag);
if (!flag) {
const x = await a(n);
// do something with x
flag = x;
console.log('flag set!');
}
console.log(`flag set at ${n} after if?`, flag);
}
}
function a(n) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(n);
});
});
}
test();
mapdoes not await, it simply turns your original array into an array of promises.for ofaround theawait.mapjust calls the callback function three times, and each of the three created promises is independent.setTimeoutcalls the callback "immediately", it's not synchronous but some minimum value - and its on the macro task loop, so being delayed after all promise stuff for sure.