ECMAScript规范中AwaitExpression返回值位置及执行逻辑问询
First, let's clarify: while await feels like syntactic sugar for Promise.prototype.then, its underlying execution model (as defined in the ECMAScript spec) has specific context management steps that explain how the Promise's value flows through to your code. Let's break down your questions one by one.
Breaking Down Your Await Execution Step Questions
1. Execution Context Stack Management for Async Functions
When an async function hits an await expression:
- The async function's execution context (
asyncContext) is suspended and removed from the execution context stack. This lets the main thread (or previous context) continue running—this is why async/await doesn't block the event loop. - The spec marks
asyncContextwith a "resumption state": when the awaited Promise settles, this context will be pushed back onto the stack, and execution will pick up right after theawaitkeyword, using the Promise's settled value as the result of theawaitexpression. - The "return to the nearest resumption operation" part refers to the event loop handling the Promise's fulfillment/rejection queue—once the Promise is ready, the runtime triggers the resumption of
asyncContext.
2. Await Fulfilled Functions & Value Propagation
The "Await Fulfilled Functions" are internal spec functions that handle the Promise's fulfilled state:
- When the Promise resolves with
value, this function usesNormalCompletion(value)to resume the suspendedasyncContext. Thisvalueis exactly what gets assigned to yourresultvariable in the async function. - The function returns
undefinedbecause its job isn't to produce a value for external code—it's purely a runtime helper to pass the resolved value into the resumed async context. The actual value you care about is carried through theNormalCompletionto theawaitexpression's evaluation result.
Where is the Await Expression's Return Value Defined in the Spec?
In the ECMAScript Language Specification, the return value of an AwaitExpression is defined in the Runtime Semantics: Evaluation section for AwaitExpression (specifically steps 6-8 in the current spec version):
- First, the expression to the right of
awaitis evaluated and converted to a Promise (let's call thispromise). - The runtime waits for
promiseto settle. If it fulfills withvalue, theawaitexpression evaluates tovalue. If it rejects withreason, theawaitexpression throwsreason(which you'd catch with atry/catchblock in the async function).
Connecting This to Your Code Example
Let's map the flow for your async function:
(async function(){ var result = await promiseA; console.log(result); // Output: "Done!" })();
- When
await promiseAruns,promiseAis already pending. The async context is suspended and removed from the stack. - 10 seconds later,
promiseAresolves with"Done!". - The Await Fulfilled Function triggers, using
NormalCompletion("Done!")to resume the async context. - The
awaitexpression's result is"Done!", which gets assigned toresult. - The
console.logruns with the resolved value.
This is analogous to how promiseA.then(...) works, but the spec uses execution context suspension/resumption to make the code read synchronously, rather than passing a callback to then.
内容的提问来源于stack exchange,提问作者MaximPro

