admin管理员组文章数量:1187855
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.
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.
Share Improve this question edited Mar 24, 2019 at 12:41 Ahmed Karaman asked Mar 24, 2019 at 12:11 Ahmed KaramanAhmed Karaman 5313 silver badges12 bronze badges 5 |4 Answers
Reset to default 16Concerning 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();
}
Focusing primarily on the last example:
let i = 3;
while (i) {
(async () => {
await Promise.resolve();
console.log(i);
i--;
})();
}
It may help if we rewrite the code without async/await to reveal what it is really doing. Under the hood, the code execution of the async function is deferred for later:
let callbacks = [];
let i = 0;
while (i > 0) {
callbacks.push(() => {
console.log(i);
i--;
});
}
callbacks.forEach(cb => {
cb();
});
As you can see, none of the callbacks are executed until after the loop is completed. Since the loop never halts, eventually the vm will run out of space to store callbacks.
Because in the first case console.log and decrement work in sync with each other because they are both inside the same asnychronous function.
In the second case console.log works asynchronously and decrement works synchronously.
Therefore, the decrement will be executed first, the asynchronous function will wait for the synchronous function to finish, then it will be executed with i == 0
In the third case, the loop body executes synchronously, and runs the asynchronous function at each iteration. Therefore, the decrement can not work until the end of the loop, so the condition in the cycle is always true. And so until the stack or memory is full
In your particular example it decrements the i
and then runs the async
code like:
let i = 3;
while (i) {
i--; // <---------------------
(async () => { // |
await Promise.resolve();// |
console.log(i); // |
})(); // |
// >---------------------------
}
Regarding your third snippet, it will never decrease the i
value and so loop runs forever and thus crashes application:
let i = 3;
while (i) {
(async () => {
await Promise.resolve(); // await and resolve >-----------
// the following code doesn't run after it resolves // |
console.log(i); // |
i--; // |
})(); // |
// out from the (async() => {})() <-------------------------
}
本文标签:
版权声明:本文标题:javascript - Why does AsyncAwait work properly when the loop is inside the async function and not the other way around? - Stack 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738337839a2077255.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
async function
s desugar to promises? – Bergi Commented Mar 24, 2019 at 13:00.then()
and.catch()
methods. Am I right ? – Ahmed Karaman Commented Mar 25, 2019 at 15:39then()
? – Bergi Commented Mar 25, 2019 at 15:41while (i) { Promise.resolve().then(res => console.log(i)); i--; }
– Ahmed Karaman Commented Mar 25, 2019 at 16:250
three times. – Bergi Commented Mar 25, 2019 at 17:44