异步函数何时实际返回挂起的承诺?

2022-02-22 00:00:00 asynchronous javascript promise

我用谷歌搜索了这个问题很多次,但我看到的唯一答案是:

异步函数始终返回承诺

但我在任何地方都找不到任何答案,这实际上是在什么时候发生的。

是在进入异步函数后立即执行,还是在遇到第一个await关键字时立即执行?

我刚刚写了这段代码:

async function main() {
  console.log(true);
  let p = await new Promise(r => setTimeout(r, 2000, 100));
  return p;
}
async function f() {
  inner(await main())

  function inner(d) {
    console.log(d + 10)
  }

  console.log('done')
}

f();

最重要的一行是:

inner(await main())

main()将首先执行,因为函数调用在优先级表中具有较高的优先级,并且异步函数返回承诺时,它将返回挂起的承诺!

但是要返回它,我们必须首先执行main(),因此它进入主执行上下文并看到console.log(true);

现在是main()返回待定承诺的位置吗?

或者它将记录此情况,然后它将到达await关键字,此时它将返回挂起的承诺?

如果这是我们的代码怎么办:

async function main() {
  (function thatTakes30SecondsToFinish() {
    // some time consuming task
  }())
  let p = await new Promise(r => setTimeout(r, 2000, 100));

  return p;
}

在这种情况下,此行inner(await main())中的main()是立即返回待定承诺,还是需要30秒才能返回待定承诺?

现在我猜是:

此行inner(await main())将立即返回挂起的承诺,但main()内的代码将继续执行,直到到达第一个等待关键字,是否正确?


解决方案

异步函数同步运行,直到到达第一个await(或函数末尾)。然后,它返回一个新的未解析承诺,该承诺将在稍后函数完成执行时得到解析。然后,异步函数的执行将暂停,调用异步函数的代码的同步执行将继续。

此行内部(await main())将立即返回挂起的承诺,但main()内的代码将继续执行,直到到达第一个等待关键字,是否正确?

没有。首先同步执行main(),直到异步主函数内部的代码达到await,然后返回承诺,继续执行f。然后,await到达f本身也返回新承诺并停止执行。

语义详情请参见specification。

相关文章