3個框框帶你理解EventLoop

花樣前端發表於2018-05-16

1、事件迴圈

大家都知道JavaScript是一門單執行緒語言

大白話講一下吧:什麼是單執行緒呢,就是主執行緒在執行程式碼時,只能從上往下一行一行執行,如果執行到某一行花費了很長時間,那麼,呵呵,沒辦法,後面的程式碼只能等著,如果執行到某一行,程式碼出錯了,呵呵,後面的也得不到執行。

但是,這樣肯定不行的。所以JavaScript引入了同步非同步的概念,把比較耗時的程式碼放到非同步API中執行,不要去阻塞主執行緒。也就有了**事件迴圈(Event Loop)**的概念

事件迴圈(Event Loop):先會執行棧中的內容,棧中內容執行後執行微任務,微任務清空後再執行巨集任務,巨集任務會在棧中執行,不停的迴圈. 如果還是不懂概念,參考這裡

2、用三個框框解釋Event Loop

不知道大家遇到過js執行順序的問題,什麼樣的組合都有,主要成員有以下幾個

  • setTimeout
  • Promise
  • setImmediate
  • Process.nextTick()

每次列印出的結果都是不按套路出牌。今天,我們就用三個框框搞懂它們,請看大螢幕。

3個框框帶你理解EventLoop

2-1、總體介紹

看圖說話。圖中一共三個框框,分別是紅色(R)、綠色(G)、藍色(B)。

執行順序:先執行紅框,再執行藍框,最後執行綠框(輔助記憶:RGB)。 這裡我們要記住執行順序,以及每個框是用來幹什麼的。

2-2、紅框

紅框是呼叫棧,所有的程式碼必須在這裡執行,當在這裡執行程式碼時,如果產生了非同步任務,那麼就按照一定類別把該非同步任務放到藍框或者綠框裡。絕對不能阻塞紅框裡的其他程式碼執行。

2-3、藍框

藍框裡放的一個個任務叫microTask,就是微任務的意思,當紅框程式碼執行完畢後,紅框就會從藍框中取出一個任務並執行,在執行過程中如果產生了其他非同步任務,那麼繼續放到藍框或者綠框裡。就這樣,藍框的一個個任務都被執行了。圖中列舉了幾個屬於microTask任務的API

2-4、綠框

綠框裡放的一個個任務叫macroTask,就是巨集任務的意思,當藍框裡的程式碼 執行完畢後,紅框就會從綠框裡取出一個任務並執行,在執行過程中如果產生了其他非同步任務,那麼繼續放到藍框或者綠框裡。就這樣,綠框的一個個任務都被執行了。圖中列舉了幾個屬於macroTask任務的API

3、哪些是macroTask,哪些是 microTask

知道了每個框的作用以及總體的執行順序後,該說一下,哪些API屬於microTask(藍框),哪些API屬於macroTask(綠框)。

microtask主要含:Promiseprocess.nextTickMutaionObserver

maicrotask主要含:setTimeoutsetIntervalsetImmediateI/O、UI互動事件

以上列出的這些API各自屬於哪個任務必須要記住。

4、練習

說了那麼多,來做幾個練習吧。 先來個一年級的

setTimeout(() => {//放到了綠框裡
    console.log(2)
}, 0);

new Promise(function (resolve) { resolve() }).then(function () {
    console.log(3)
})//放到了藍框裡

console.log(1)//預設在紅框裡,不動
複製程式碼

以上程式碼的結果是1、3、2

解釋一波吧:

  • 這段程式碼首先整體作為一個巨集任務(macroTask)進入到紅框。
  • 先遇到setTimeout,那麼將其回撥函式註冊後分發到巨集任務中,就是綠框裡邊。
  • 然後遇到了Promisethen函式分發微任務到微任務中,就是藍框裡。
  • 遇到console.log(),立即執行。
  • 到這裡,整體程式碼作為第一個巨集任務就執行結束了。接下來,該去藍框看看了,發現有then,執行。
  • 然後再到綠框裡拿出setTimeout的註冊回撥函式,執行
  • 結束。

再來一道複雜點兒的吧

console.log(1)

setTimeout(() => {
    console.log(2);
    process.nextTick(function () {
        console.log(3);
    })
}, 0);

process.nextTick(function () {
    console.log(4)
})

new Promise(function (resolve) {
    console.log(5);
    resolve()
}).then(function () {
    console.log(6)
})
複製程式碼

以上程式碼執行結果為:1、5、4、6、2、3

分析過程留給大家吧,只要按照我們一開始說的,把所有的非同步任務分門別類的放到對應的框框裡,然後再按照RGB的順序去執行,我相信,你能做對的。

相關文章