2 回答
TA贡献1875条经验 获得超5个赞
这是一个不会冻结浏览器的替代演示(我认为这是我们试图展示的方式),它显示了与您最初的结论相反的行为:
const p = new Promise((r) => r());
p.then(() => {
(async() => {
console.log('a');
await p;
console.log('p');
})()
console.log('b');
});
在这种情况下,我们得到p
一个已解决的承诺。然后我们启动一个等待它的异步函数。输出是:
一个
bp
_
IE 异步函数在点击已经解析的b
时仍然返回控制权(并被记录)。只有在被记录之后,事件循环才可以自由地返回到随后被记录之后的执行。await
p
b
await
p
这是标准行为吗?是的。
该规范有效地将等待的表达式转换为then
承诺的一部分,并在后续步骤的第 9 步和第 10 步中决定如何进行。
如果 promise.[[PromiseState]] 处于待定状态,则
a. 将 fulfillReaction 添加为列表的最后一个元素,即 promise.[[PromiseFulfillReactions]]。
b. 附加 rejectReaction 作为 List 的最后一个元素,即 promise.[PromiseRejectReactions]]。否则如果 promise.[[PromiseState]] 被履行,
a。然后让价值成为承诺。[[PromiseResult]]。
b. 设 fulfillJob 为 NewPromiseReactionJob(fulfillReaction, value)
c。执行 HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]])。
第 9 步表示如果它处于待处理状态,则将生成的添加到then
承诺履行时要调用的事物列表中。
第 10 步是您问题的核心——它说如果它已经完成,则将作业排入队列——即将它放在要回调的队列中。
规范有效地说明了 anawait
永远不应该同步返回。
TA贡献1757条经验 获得超8个赞
这是预期的行为。您在那里冻结了事件循环,因为承诺已经解决,下一个 await 运算符将在事件循环的同一迭代中等待并解决下一个承诺描述符。但这种行为可能是特定于平台的,具体取决于您实际使用的是哪种 promise 实现 - 本机或 shim。
const promise= Promise.resolve();
(async()=>{
for(let i=0; i< 10000000; i++) {
await promise;
}
console.log('end');
})()
setTimeout(()=> console.log('nextEventLoopTick'), 0);
会输出如下:
end
nextEventLoopTick
如您所见,async fn 将在 setTimeout 之前完全解析。因此,这表明异步函数是在同一个事件循环滴答上解析的。
添加回答
举报