我尝试遵循 ECMAScript 规范来了解如何 async/await
做它的工作并遇到了一些障碍。
假设有这样的代码:
function boo() {
return 1;
}
async function foo() {
let result = await boo();
return result;
}
foo();
因此,让我们开始逐步跟踪幕后必须完成的工作:
正在运行
[[Call]]
foo()
的内部方法,暂停当前执行上下文(callerContext
),创建新的(calleeContext
)并将其插入执行上下文堆栈。我们有这样的执行上下文堆栈:callerContext < calleeContext -- running
.下一步是
foo()
评估(即AsyncFunctionBody
与之关联),实际上是EvaluateAsyncFunctionBody
.此例程依次调用AsyncFunctionStart
.它创建了正在运行的执行上下文的副本 -asyncContext
- 并将其压入堆栈,现在如下所示:callerContext < calleeContext < asyncContext -- running
.calleeContext
急于收到asyncContext
的结果稍后评估(第 10 步)。按照
AsyncFunctionStart
中的规定,asyncContext
评估FunctionBody
的foo()
.await
表达是一路上遇到的。是defined得到boo()
的结果首先和随后调用Await
例行程序1
作为论点。Await
创建一个用1
解决的 promise 并执行其then()
,这样 promise 就可以通知其已实现的值,并且该值将作为await
的结果公开。表达。但是现在asyncContext
从执行上下文堆栈中删除,当前为callerContext < calleeContext -- running
.
我很难理解接下来会发生什么。 promise 仅在执行上下文堆栈为空时才利用机会通知其订阅者,因为为了它 Job
涉及队列。另一方面,caleeContext
正在等待 asyncContext
的结果评估(AsyncFunctionStart
的第 10 步),我找不到从堆栈中删除两个执行上下文(calleeContext
和 callerContext
)的位置。这似乎是一个僵局!
最佳答案
caleeContext
is waiting for the result ofasyncContext
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/