javascript - 对async/await求值细节的误解

标签 javascript async-await

我尝试遵循 ECMAScript 规范来了解如何 async/await做它的工作并遇到了一些障碍。

假设有这样的代码:

function boo() {
    return 1;
}

async function foo() {
    let result = await boo();
    return result;
}

foo();

因此,让我们开始逐步跟踪幕后必须完成的工作:

  1. 正在运行 [[Call]] foo()的内部方法,暂停当前执行上下文(callerContext),创建新的(calleeContext)并将其插入执行上下文堆栈。我们有这样的执行上下文堆栈:callerContext < calleeContext -- running .

  2. 下一步是 foo()评估(即 AsyncFunctionBody 与之关联),实际上是 EvaluateAsyncFunctionBody .此例程依次调用 AsyncFunctionStart .它创建了正在运行的执行上下文的副本 - asyncContext - 并将其压入堆栈,现在如下所示:callerContext < calleeContext < asyncContext -- running . calleeContext急于收到 asyncContext 的结果稍后评估(第 10 步)。

  3. 按照AsyncFunctionStart中的规定, asyncContext评估 FunctionBodyfoo() . await表达是一路上遇到的。是defined得到 boo() 的结果首先和随后调用 Await 例行程序 1作为论点。

  4. Await创建一个用 1 解决的 promise 并执行其 then() ,这样 promise 就可以通知其已实现的值,并且该值将作为 await 的结果公开。表达。但是现在asyncContext从执行上下文堆栈中删除,当前为 callerContext < calleeContext -- running .

我很难理解接下来会发生什么。 promise 仅在执行上下文堆栈为空时才利用机会通知其订阅者,因为为了它 Job 涉及队列。另一方面,caleeContext正在等待 asyncContext 的结果评估(AsyncFunctionStart 的第 10 步),我找不到从堆栈中删除两个执行上下文(calleeContextcallerContext)的位置。这似乎是一个僵局!

最佳答案

caleeContext is waiting for the result of asyncContext evaluation

不是真正的“等待”。正如你所说,await keyword从调用堆栈中删除 asyncContext,并在 AsyncFunctionStart 的第 6 步中返回 1 undefined 2。完成后,EvaluateAsyncFunctionBody 的第 5 步确实返回 promise 结果。有了这个结果,[[Call]] 的第 7 步已完成,第 8 步执行“从执行上下文堆栈中删除 calleeContext 并将 callerContext 恢复为正在运行的执行上下文。”。现在 foo() 已经返回了 promise 。

callerContext 最终在 ScriptEvaluation 的第 14 步中从堆栈中移除- 它是全局 scriptContext

1:另请参阅 Await 中的注释(第 15 步):“这将返回到对 asyncContext< 之前恢复评估的操作的评估.
2:另请参阅AsyncFunctionStart 中的断言(第 7 步和第 8 步):“当我们返回此处时,asyncContext 已从执行上下文堆栈中删除并且 runningContext 是当前运行的执行上下文。result 是正常完成,值为 undefined。[A] 完成值的可能来源 [is] 等待"。

关于javascript - 对async/await求值细节的误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68123310/

相关文章:

python - 基于生成器的协程与原生协程

javascript - 如何处理循环中的引用?

Javascript navigator.mediaDevices.getUserMedia 将源移动到前面

javascript - 从动态创建的 div 数组注册 onclick 事件? Rails + Jquery?

c# - .NET Async 中的可伸缩性与响应能力

.net - 在 Azure 云服务运行覆盖中使用等待

javascript - 如何使HTML中的按钮消失?

c# - 使用 C# 使用数据库中的新数据每 1 分钟更新一次 Google Maps Javascript 对象?

sql-server - ExecuteReaderAsync 导致 sql 查询需要更长时间才能完成?

javascript - Promise.alls 并等待