當前位置:
首頁 > 科技 > 總是一知半解的Event Loop

總是一知半解的Event Loop

前言

今日早讀文章由美團金融大前端團隊 @ 孫宇輝投稿分享。

正文從這開始~

JavaScript中的事件循環一直都是一個很多人都或多或少了解,但說不清楚的知識點,停留在一知半解的層面。以前只需要使用回調函數、定時器還好說,但是自從有了Promise之後,對事件循環的透徹了解就比較重要了。

本篇文章不打算從頭開始敘述,那樣篇幅太長,略過最基本的概念,我們簡單粗暴的把事件循環說清楚。

理論:關於MacroTask和MicroTask

一張圖展示JavaScript中的事件循環:

一次事件循環:先運行macroTask隊列中的一個,然後運行microTask隊列中的所有任務。接著開始下一次循環(只是針對macroTask和microTask,一次完整的事件循環會比這個複雜的多)。

其中macroTask和microTask是兩種任務隊列,相比而言,大家更熟悉的一個詞是任務隊列(task queue,其實就是macroTask),大家更熟悉的關於事件循環的機制說法大概是:主進程執行完了之後,每次從任務隊列里取一個任務執行。但是promise出現之後,這個說法就不太準確了。

JavaScript引擎對這兩種隊列有不同的處理,簡單的說就是引擎會把我們的所有任務分門別類,一部分歸為macroTask,另外一部分歸為microTack,下面是類別劃分:

macroTask: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering

microTask: process.nextTick, Promise, Object.observe, MutationObserver

我們所熟悉的定時器就屬於macroTask,但是僅僅了解macroTask的機制還是不夠的。

上面這些都是理論啊,我們怎麼直觀的感受兩種隊列的區別呢?說的再多也不如來一段實踐,我們感知這種區別最好的方式就是通過任務的執行順序。

實踐:小二,上代碼

我們以setTimeout、process.nextTick、promise為例直觀感受下兩種任務隊列的運行方式。

console.log( main1 );

process.nextTick(function(){

console.log( process.nextTick1 );

});

setTimeout(function(){

console.log( setTimeout );

process.nextTick(function(){

console.log( process.nextTick2 );

});

},);

newPromise(function(resolve,reject){

console.log( promise );

resolve();

}).then(function(){

console.log( promise then );

});

console.log( main2 );

別著急看答案,先以上面的理論自己想想,運行結果會是啥?

最終結果是這樣的:

main1

promise

main2

process.nextTick1

promise then

setTimeout

process.nextTick2

process.nextTick 和 promise then在 setTimeout 前面輸出,已經證明了macroTask和microTask的執行順序。但是有一點必須要指出的是。上面的圖容易給人一個錯覺,就是主進程的代碼執行之後,會先調用macroTask,再調用microTask,這樣在第一個循環里一定是macroTask在前,microTask在後。

但是最終的實踐證明:在第一個循環里,process.nextTick1和promise then這兩個microTask是在setTimeout這個macroTask里之前輸出的,這是為什麼呢?

因為主進程的代碼也屬於macroTask(這一點我比較疑惑的是主進程都是一些同步代碼,而macroTask和microTask包含的都是一些非同步任務,為啥主進程的代碼會被劃分為macroTask,不過從實踐來看確實是這樣,而且也有理論支撐:【翻譯】Promises/A+規範)。

主進程這個macroTask(也就是main1、promise和main2)執行完了,自然會去執行process.nextTick1和promise then這兩個microTask。這是第一個循環。之後的setTimeout和process.nextTick2屬於第二個循環

別看上面那段代碼好像特別繞,把原理弄清楚了,都一樣 ~

requestAnimationFrame、Object.observe(已廢棄) 和 MutationObserver這三個任務的運行機制大家可以從上面看到,不同的只是具體用法不同。重點說下UI rendering。在HTML規範:event-loop-processing-model里敘述了一次事件循環的處理過程,在處理了macroTask和microTask之後,會進行一次Update the rendering,其中細節比較多,總的來說會進行一次UI的重新渲染。

後續

不知道大家有沒有發現一個現象,在學習技術點的時候,如果太淺,得來的知識點可能不完整甚至是錯的,如果追究的太深,又會給人一種太偏學究的感覺,其中的平衡點,大家自己留心把握。

參考:

HTML規範:event-loop-processing-model

【翻譯】Promise/A 規範

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

美團金融大前端團隊招各級別前端工程師
手把手教你用ngrx管理Angular狀態(下)
手把手教你用ngrx管理Angular狀態(上)
「大產品小細節」Hick『s Law 希克法則
認識 V8 引擎

TAG:前端早讀課 |

您可能感興趣

《黑豹》總是給人一種made in China的既視感
為什麼iPhone總是比iPad貴?
Air Jordan鞋款總是更勝一籌?比atmos x Nike Air Max還狂野!
Win7系統屏幕總是會顯示brightness如何解決?
我們總是在說的巴黎風-那種Effortless Chic到底是怎麼來的?
蘋果公布iOS beta1等系統 bug總是要修的!
Angelababy:出來混總是要還的
G?知 明星們總是完美無瑕?Blake Lively坦誠99.9%的照片都是PS的!
Supreme聯名總是瘋狂撞衫?The North Face全新金屬系列才更值得入!
iPhone6S plus總是降頻怎麼辦?別擔心,注意這些小細節就行了
PINK《sober》聽她的音樂總是那麼過癮
《Sugar Man》少時Sunny吐槽Henry:總是問跟我結婚能不能拿SM股份
明星們總是完美無瑕?Blake Lively坦誠99.9%的照片都是PS的!
彩妝盤總是有雞肋色?innisfree了解一下!
Luisa Beccaria F/W 2018 少女情懷總是詩
為什麼Chinglish總是聽起來沒有禮貌?
為什麼明星總是buling buling,因為她們展「飾」了不一樣的自己呀
模特Rocio Crusset休閑度假,網友:她總是那麼嬌小可愛!
《湮滅Annihilation(2018)》人們對未知事物總是充滿恐懼,也許人類最大的敵人就是自己
美好的事物總是姍姍來遲,PlayStation 5真的可能在近期到來?