好家伙,本篇為做題思考
書接上文
題目如下:
1.請給出下列代碼的輸出結果,并配合"訊息佇列"寫出相關解釋
async function foo() { console.log(2); console.log(await Promise.resolve(8)); console.log(9); } async function bar() { console.log(4); console.log(await 6); console.log(7); } console.log(1); foo(); console.log(3); bar(); console.log(5);
好我們公布答案:
(1) 列印 1;
(2) 呼叫異步函式 foo();
(3)(在 foo()中)列印 2;
(4)(在 foo()中)await 關鍵字暫停執行,向訊息佇列中添加一個期約在落定之后執行的任務;
(5) 期約立即落定,把給 await 提供值的任務添加到訊息佇列;
(6) foo()退出;
(7) 列印 3;
(8) 呼叫異步函式 bar();
(9)(在 bar()中)列印 4;
(10)(在 bar()中)await 關鍵字暫停執行,為立即可用的值 6 向訊息佇列中添加一個任務;
(11) bar()退出;
(12) 列印 5;
(13) 頂級執行緒執行完畢;
(14) JavaScript 運行時從訊息佇列中取出解決 await 期約的處理程式,并將解決的值 8 提供給它;
(15) JavaScript 運行時向訊息佇列中添加一個恢復執行 foo()函式的任務;
(16) JavaScript 運行時從訊息佇列中取出恢復執行 bar()的任務及值 6;
(17)(在 bar()中)恢復執行,await 取得值 6;
(18)(在 bar()中)列印 6;
(19)(在 bar()中)列印 7;
(20) bar()回傳;
(21) 異步任務完成,JavaScript 從訊息佇列中取出恢復執行 foo()的任務及值 8;
(22)(在 foo()中)列印 8;
(23)(在 foo()中)列印 9;
(24) foo()回傳,
所以答案是
1
2
3
4
5
6
7
8
9
好了,結束了,沒什么問題了
步驟也解釋清楚了
但是我隱約感到了不對勁
怎么會是123456789呢?
foo()應該是先恢復的,但是這里明顯bar()先恢復了
我們上機試一下


誒,結果不對
前面地12345都沒有問題,6789的輸出變成了8967
我們主要來看和6789有關的輸出欄位
我們再來仔細地看看前面地解釋,并把關鍵解釋劃出來
(4)(在 foo()中)await 關鍵字暫停執行,向訊息佇列中添加一個期約在落定之后執行的任務;
(5) 期約立即落定,把給 await 提供值的任務添加到訊息佇列;
(6) foo()退出;
(10)(在 bar()中)await 關鍵字暫停執行,為立即可用的值 6 向訊息佇列中添加一個任務;
(11) bar()退出;
(13) 頂級執行緒執行完畢;
(14) JavaScript 運行時從訊息佇列中取出解決 await 期約的處理程式,并將解決的值 8 提供給它;
(15) JavaScript 運行時向訊息佇列中添加一個恢復執行 foo()函式的任務;
(16) JavaScript 運行時從訊息佇列中取出恢復執行 bar()的任務及值 6;
我們回顧一下訊息佇列
一個 JavaScript 運行時包含了一個待處理訊息的訊息佇列,. 每一個訊息都關聯著一個用以處理這個訊息的回呼函式,
再補充一個關于await的知識點
等到 await 右邊的值可用了,JavaScript 運行時會向訊息 佇列中推送一個任務,這個任務會恢復異步函式的執行,
我們試著把這個訊息佇列畫出來

(有點抽象,但應該能看懂)
這樣,我們就會發現, 因為Promise.resolve(8)被多處理了一次,導致了foo()方法后恢復
所以bar()先恢復了
那么實際上機又是怎么回事呢?
(書里面有行小字被我忽略了,后面又找到了)

TC39 對 await 后面是期約的情況如何處理做過一次修改,修改后,本例中的 Promise.resolve(8)只會生成一個 異步任務,
因此在新版瀏覽器中,這個示例的輸出結果為 123458967,實際開發中,對于并行的異步操作我們通常 更關注結果,而不依賴執行順序,——譯者注
實際上機的訊息佇列

原先的兩步處理變成了一步
搞定了,原來如此
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/546365.html
標籤:其他
上一篇:前端如何相對優雅管理api
下一篇:天機-免費的新一代資料安全網關
