JavaScript Async/Await 逻辑表现为同步

joa*_*des 0 javascript async-await es6-promise

如果我理解正确的话,用关键字async声明的函数应该返回一个承诺。对于async3函数,我们有 10 亿次迭代,这使得返回值需要更长的时间。分析下面的代码,我期望发生的是,通过调用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));
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么它会这样吗?我缺少什么?

我所期望的:

sync1(); // console logged immediately
sync2(); // console logged immediately
async3().then((val) => console.log(val)); // console logged moments later
Run Code Online (Sandbox Code Playgroud)

目前发生的事情:

     同步1(); // async3 完成后控制台记录
     同步2(); // async3 完成后控制台记录
     async3().then((val) => console.log(val)); // async3 完成后控制台记录

Cer*_*nce 5

请记住,JavaScript 本质上是单线程的。

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

  while (iteration <= 1000000000) {
    number = iteration;
    iteration++;
  }
Run Code Online (Sandbox Code Playgroud)

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

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

另一种解决方案是在工作线程中执行计算量大的async3函数,该函数位于单独的线程上,这不会阻塞浏览器的主线程。