1. 程式人生 > >promise.then, setTimeout,await執行順序問題

promise.then, setTimeout,await執行順序問題

IV 多個 並發 訪問 理解 sta targe 任務 原因

  • promise.then VS setTimeout

技術分享圖片

  在chrome和node環境環境中均輸出2, 3, 1, 先輸出2沒什麽好說的,3和1順序讓人有些意外

原因

有一個事件循環,但是任務隊列可以有多個。

整個script代碼,放在了macrotask queue中,setTimeout也放入macrotask queue。

但是,promise.then放到了另一個任務隊列microtask queue中。

這兩個任務隊列執行順序如下,取1個macrotask queue中的task,執行之。

然後把所有microtask queue順序執行完,再取macrotask queue中的下一個任務。

代碼開始執行時,所有這些代碼在macrotask queue中,取出來執行之。

後面遇到了setTimeout,又加入到macrotask queue中,

然後,遇到了promise.then,放入到了另一個隊列microtask queue。

等整個execution context stack執行完後,

下一步該取的是microtask queue中的任務了。

因此promise.then的回調比setTimeout先執行。

  • await

async function a() {
    await console.log(1)
    console.log(2)
}

async function b() {
    await a();
}

b();

console.log(3)

輸出: 1, 3, 2

async function a() {
    await console.log(1)
    console.log(2)
}

async function b() {
    await a();
}

b();

setTimeont(function(){console.log(3)},0)
輸出: 1, 2, 3

await不會造成程序阻塞,只是promise的語法糖,可以看看babel編譯後async/await, 可以這麽理解,async 是多個異步操作的promise對象,await相當於then,代碼執行跟你用callback寫的代碼並沒有什麽區別,本質上並不是同步代碼,只是讓你思考代碼邏輯的時候能夠以同步的思維去思考,避開回調地獄,要理解異步,首先要理解cpu的工作方式,cpu執行代碼的時候,一個周期是以時間片為單位,實際上,無論是php還是node,處理同一個請求,cpu需要的計算量是一樣的,在同樣的時間內,cpu能做的計算量是一樣的,差別在於,node只是提高了cpu的利用率。從而提高了同一時間能處理的請求數量。 打個比方,你去銀行辦理業務,只有一個窗口在辦理業務(一個cpu進程),假設有兩個人(A和B)要辦理銀行卡(可理解為一次請求),方式一:A到窗口前,但這個時候要辦卡的話,櫃員告訴你,要你的身份證復印件(可理解為IO操作),這個時候,你去復印,櫃員等待,回來後繼續辦理,A辦理完成後,B接著同樣的步驟。方式二:在A去復印身份證的時候,櫃員受理B的辦理請求, 等A回來後再受理A的業務。所以,很明顯,方式二在同樣多的時間內,一個窗口能辦理的銀行卡數量更多,因為這種方式充分利用了櫃員等待的時間,那麽方式一就是php處理請求的方式,在PHP中,處理IO操作的時候(比如,訪問數據庫,讀取文件等),實際上cpu是處於等待狀態,但其他資源此時得不到cpu的計算資源,屬於資源浪費,cpu並沒有接受下一個請求,而方式二,則是node處理的方式。所以綜上所述,async/await 並不會影響node的並發數量,async/await是以同步的思維去寫異步的代碼。

promise.then, setTimeout,await執行順序問題