当循环在异步函数内部而不是相反时,为什么异步/等待正常工作?

Ahm*_*man 16 javascript async-await es6-promise

我有三个片段是循环三次,而await在荷兰国际集团promise

在第一个代码段中,它按我的预期工作,并且i每个的值都递减await

let i = 3;

(async () => {
  while (i) {
    await Promise.resolve();
    console.log(i);
    i--;
  }
})();
Run Code Online (Sandbox Code Playgroud)

输出:

3
2
1
Run Code Online (Sandbox Code Playgroud)

在第二个中,的值i连续递减直到其达到零,然后await执行所有s。

let i = 3;

while (i) {
  (async () => {
    await Promise.resolve();
    console.log(i);
  })();
  i--;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0
0
0
Run Code Online (Sandbox Code Playgroud)

最后,这将导致Allocation failed - JavaScript heap out of memory错误并且不输出任何值。

let i = 3;
while (i) {
  (async () => {
    await Promise.resolve();
    console.log(i);
    i--;
  })();
}
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么他们表现出这些不同的行为吗?谢谢。

Jon*_*lms 15

关于第二个片段:

在不等待结果的情况下对异步函数进行校准被称为fire and fuck 。您告诉JavaScript它应该开始一些异步处理,但是您不在乎它何时以及如何完成。就是这样 它循环,触发一些异步任务,当循环完成时它们会在完成时返回,并在循环已经结束时记录为0。如果您愿意:

await (async () => {
  await Promise.resolve();
  console.log(i);
})();
Run Code Online (Sandbox Code Playgroud)

它将按顺序循环。

关于您的第三个片段:

您永远不会减少i循环,因此循环将永远运行。i如果异步任务在某些时候执行会减少,但是这不会发生,因为while循环会疯狂运行并阻塞浏览器并使之崩溃。

 let i = 3;
 while(i > 0) {
   doStuff();
 }
Run Code Online (Sandbox Code Playgroud)


Joe*_*ett 9

主要关注最后一个示例:

let i = 3;
while (i) {
  (async () => {
    await Promise.resolve();
    console.log(i);
    i--;
  })();
}
Run Code Online (Sandbox Code Playgroud)

如果我们在不进行异步/等待的情况下重写代码以揭示其实际功能,则可能会有所帮助。在幕后,异步函数的代码执行推迟到以后:

let callbacks = [];

let i = 0;
while (i > 0) {
  callbacks.push(() => {
    console.log(i);
    i--;
  });
}

callbacks.forEach(cb => {
  cb();
});
Run Code Online (Sandbox Code Playgroud)

如您所见,在循环完成之前,不会执行任何回调。由于循环永远不会停止,因此最终虚拟机将用光空间来存储回调。