I have three snippets that loop three times while await
ing on a promise
.
In the first snippet, it works as I expect and the value of i
is decremented with each await
.
let i = 3;
(async () => {
while (i) {
await Promise.resolve();
console.log(i);
i--;
}
})();
Output:
3
2
1
In the second one, the value of i
is continuously decremented until it reaches zero and then all the await
s are executed.
let i = 3;
while (i) {
(async () => {
await Promise.resolve();
console.log(i);
})();
i--;
}
Output:
0
0
0
Lastly, this one causes an Allocation failed - JavaScript heap out of memory
error and doesn't print any values.
let i = 3;
while (i) {
(async () => {
await Promise.resolve();
console.log(i);
i--;
})();
}
Can someone explain why they exhibit these different behaviors? Thanks.
async and await are both meta keywords that allow asynchronous code to be written in a way that looks synchronous. An async function tells the compiler ahead of time that the function will be returning a Promise and will not have a value resolved right away. To use await and not block the thread async must be used.
You need to place the loop in an async function, then you can use await and the loop stops the iteration until the promise we're awaiting resolves. You could also use while or do.. while or for loops too with this same structure.
An async function can contain an await expression, that pauses the execution of the function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value. You can think of a Promise in JavaScript as the equivalent of Java's Future or C# 's Task.
The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.
Concerning your second snippet:
Caling an async function without awaiting it's result is called fire and forget. You tell JavaScript that it should start some asynchronous processing, but you do not care when and how it finishes. That's what happens. It loops, fires some asynchronous tasks, when the loop is done they somewhen finish, and will log 0 as the loop already reached its end. If you'd do:
await (async () => {
await Promise.resolve();
console.log(i);
})();
it will loop in order.
Concerning your third snippet:
You never decrement i
in the loop, therefore the loop runs forever. It would decrement i
if the asynchronous tasks where executed somewhen, but that does not happen as the while loop runs crazy and blocks & crashes the browser.
let i = 3;
while(i > 0) {
doStuff();
}
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