JavaScript Async/Await 逻辑表现为同步

JavaScript Async/Await logic behaving as synchronous

如果我理解正确,用关键字 async 声明的函数应该 return 一个承诺。在 async3 函数的情况下,我们有 10 亿次迭代,这使得 return 值需要更长的时间。分析下面的代码,我期望发生的是,通过调用 sync1sync2 函数,立即登录控制台,稍后, async3 函数日志会来。但是,我注意到 sync1sync2 函数仅在 async3 结束后记录. async3 函数难道不应该 运行 在另一个线程上或在事件循环之外而不阻塞在运行时调用的其他函数的执行吗?

function sync1() {
  console.log(1);
}

function sync2() {
  console.log(2);
}

async function async3() {
  let iteration = 0;
  let number = 0;
  while (iteration <= 1000000000) {
    number = iteration;
    iteration++;
  }
  return number;
}

sync1();
sync2();
async3().then((val) => console.log(val));

你能解释一下为什么会这样吗?我错过了什么?

我的预期:

sync1(); // console logged immediately
sync2(); // console logged immediately
async3().then((val) => console.log(val)); // console logged moments later

当前发生的事情:


     sync1(); // console logged after async3 is done 
     sync2(); // console logged after async3 is done
     async3().then((val) => console.log(val)); // console logged after async3 is done

请记住,JavaScript 基本上是 single-threaded。

虽然 async3 是异步的,但其操作 完全同步 ,并且 CPU 密集。一旦浏览器有一点空闲时间,输出只会(视觉上)打印到控制台,但以下块:

  while (iteration <= 1000000000) {
    number = iteration;
    iteration++;
  }

在上述计算完成之前,浏览器不会有空闲时间。

为了 sync1sync2 立即记录,一个解决方案是让 async3 每 100,000 次迭代(或其他)暂停,并等待 setTimeout,从而使浏览器有机会执行诸如向控制台显示内容、处理其他事件侦听器、呈现更改等操作。

另一种解决方案是在 worker 中执行 computation-heavy async3 函数,它在一个单独的线程上,不会阻塞浏览器的主线程。