2 回答

TA貢獻(xiàn)1875條經(jīng)驗(yàn) 獲得超5個(gè)贊
這是一個(gè)不會(huì)凍結(jié)瀏覽器的替代演示(我認(rèn)為這是我們?cè)噲D展示的方式),它顯示了與您最初的結(jié)論相反的行為:
const p = new Promise((r) => r());
p.then(() => {
? (async() => {
? ? console.log('a');
? ? await p;
? ? console.log('p');
? })()
? console.log('b');
});
在這種情況下,我們得到p
一個(gè)已解決的承諾。然后我們啟動(dòng)一個(gè)等待它的異步函數(shù)。輸出是:
一個(gè)
bp
_
IE 異步函數(shù)在點(diǎn)擊已經(jīng)解析的b
時(shí)仍然返回控制權(quán)(并被記錄)。只有在被記錄之后,事件循環(huán)才可以自由地返回到隨后被記錄之后的執(zhí)行。await
p
b
await
p
這是標(biāo)準(zhǔn)行為嗎?是的。
該規(guī)范有效地將等待的表達(dá)式轉(zhuǎn)換為then
承諾的一部分,并在后續(xù)步驟的第 9 步和第 10 步中決定如何進(jìn)行。
如果 promise.[[PromiseState]] 處于待定狀態(tài),則
a.?將 fulfillReaction 添加為列表的最后一個(gè)元素,即 promise.[[PromiseFulfillReactions]]。
b.?附加 rejectReaction 作為 List 的最后一個(gè)元素,即 promise.[PromiseRejectReactions]]。否則如果 promise.[[PromiseState]] 被履行,
a。然后讓價(jià)值成為承諾。[[PromiseResult]]。
b.?設(shè) fulfillJob 為 NewPromiseReactionJob(fulfillReaction, value)
c。執(zhí)行 HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]])。
第 9 步表示如果它處于待處理狀態(tài),則將生成的添加到then
承諾履行時(shí)要調(diào)用的事物列表中。
第 10 步是您問題的核心——它說如果它已經(jīng)完成,則將作業(yè)排入隊(duì)列——即將它放在要回調(diào)的隊(duì)列中。
規(guī)范有效地說明了 anawait
永遠(yuǎn)不應(yīng)該同步返回。

TA貢獻(xiàn)1757條經(jīng)驗(yàn) 獲得超8個(gè)贊
這是預(yù)期的行為。您在那里凍結(jié)了事件循環(huán),因?yàn)槌兄Z已經(jīng)解決,下一個(gè) await 運(yùn)算符將在事件循環(huán)的同一迭代中等待并解決下一個(gè)承諾描述符。但這種行為可能是特定于平臺(tái)的,具體取決于您實(shí)際使用的是哪種 promise 實(shí)現(xiàn) - 本機(jī)或 shim。
const promise= Promise.resolve();
(async()=>{
for(let i=0; i< 10000000; i++) {
await promise;
}
console.log('end');
})()
setTimeout(()=> console.log('nextEventLoopTick'), 0);
會(huì)輸出如下:
end
nextEventLoopTick
如您所見,async fn 將在 setTimeout 之前完全解析。因此,這表明異步函數(shù)是在同一個(gè)事件循環(huán)滴答上解析的。
添加回答
舉報(bào)