亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

深入分析JavaScript 事件循環(Event Loop)

瀏覽:19日期:2023-10-23 11:47:27

事件循環(Event Loop),是每個JS開發者都會接觸到的概念,但是剛接觸時可能會存在各種疑惑。

眾所周知,JS是單線程的,即同一時間只能運行一個任務。一般情況下這不會引發問題,但是如果我們有一個耗時較多的任務,我們必須等該任務執行完畢才能進入下一個任務,然而等待的這段時間常常讓我們無法忍受,因為我們這段時間什么都不能做,包括頁面也是鎖死狀態。

好在,時代在進步,瀏覽器向我們提供了JS引擎不具備的特性:Web API。Web API包括DOM API、定時器、HTTP請求等特性,可以幫助我們實現異步、非阻塞的行為。我們可以通過異步執行任務的方法來解決單線程的弊端,事件循環為此而生。

提問QAQ:為什么JavaScript是單線程的?

多個線程表示您可以同時獨立執行程序的多個部分。確定一種語言是單線程還是多線程的最簡單方法是看它擁有有多少個調用堆棧。JS 只有一個,所以它是單線程語言。

將JS設計為單線程是由其用途運行環境等因素決定的,作為瀏覽器腳本語言,JS的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。同時,單線程執行效率高。

1. Event Loop舊印象

大家熟悉的關于事件循環的機制說法大概是:主進程執行完了之后,每次從任務隊列里取一個任務執行。如圖所示,所有的任務分為同步任務和異步任務,同步任務直接進入任務隊列-->主程序執行;異步任務則會掛起,等待其有返回值時進入任務隊列從而被主程序執行。異步任務會通過任務隊列的機制(先進先出的機制)來進行協調。具體如圖所示:

深入分析JavaScript 事件循環(Event Loop)

同步和異步任務分別進入不同的執行環境,同步的進入主線程,即主執行棧,異步的進入任務隊列。主線程內的任務執行完畢為空,會去任務隊列讀取對應的任務,推入主線程執行。 上述過程的不斷重復就是我們所熟悉的Event Loop (事件循環)。但是promise出現之后,這個說法就不太準確了。

2. Event Loop 后印象

2.1 理論

這里首先用一張圖展示JavaScript的事件循環:

深入分析JavaScript 事件循環(Event Loop)

直接看這張圖,可能黑人問號已經出現在同學的腦海。。。

這里將task分為兩大類,分別是macroTask(宏任務)和microTask(微任務).一次事件循環:先運行macroTask隊列中的一個,然后運行microTask隊列中的所有任務。接著開始下一次循環(只是針對macroTask和microTask,一次完整的事件循環會比這個復雜的多)。

那什么是macroTask?什么是microTask呢?

JavaScript引擎把我們的所有任務分門別類,一部分歸為macroTask,另外一部分歸為microTack,下面是類別劃分:

macroTask:

setTimeout setInterval setImmediate requestAnimationFrame I/O UI rendering

microTask:

process.nextTick Promise Object.observe MutationObserver

我們所熟悉的定時器就屬于macroTask,僅僅了解macroTask的機制還是不夠的。為直觀感受兩種隊列的區別,下面上代碼進行實踐感知。

2.2 實踐

以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’); });}, 0);new Promise(function(resolve, reject) { console.log(’promise’); resolve();}).then(function() { console.log(’promise then’);});console.log(’main2’);

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

最終結果是這樣的:

main1promisemain2process.nextTick1promise then

// 第二次事件循環setTimeoutprocess.nextTick2

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

但是最終的實踐證明:在第一個循環里,process.nextTick1和promise then這兩個microTask是在setTimeout這個macroTask里之前輸出的,這是因為Promises/A+規范規定主進程的代碼也屬于macroTask。

主進程這個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的重新渲染。

3. 小結

總而言之,記住一次事件循環:先運行macroTask隊列中的一個,然后運行microTask隊列中的所有任務。接著開始下一次循環。

參考文獻:

JavaScript Event Loop相關原理解析 深入理解事件循環機制 JavaScript運行機制

以上就是深入分析JavaScript 事件循環(Event Loop)的詳細內容,更多關于JavaScript 事件循環(Event Loop)的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 亚洲国产毛片aaaaa无费看 | 精品国产视频在线观看 | 免费在线亚洲 | 国产乱小说 | 色久综合在线 | 国产福利视精品永久免费 | 成人性色生活片免费看爆迷你毛片 | 视频一区 国产 | 青青草国产精品久久久久 | 三级精品 | 国产一级毛片视频在线! | 亚洲系列中文字幕一区二区 | 国产精彩对白综合视频 | 国产成人99久久亚洲综合精品 | 国产精品高清一区二区 | 国产精选一区二区 | 日韩毛片在线观看 | 毛片毛片毛片 | 欧美一级毛片免费大片 | 桃花阁成人网在线观看 | 欧美啪啪网站 | 伊人222综合| 欧美色视频日本片高清在线观看 | 特黄特黄特色大片免费观看 | 久久国产精品久久久 | 99re热久久 | 九九久久久久午夜精选 | 99re九精品视频在线视频 | 91精品国产视频 | 爱爱欧美视频 | 日本a级特黄特黄刺激大片 日本a黄 | 我要看一级黄色 | 欧美在线精品一区二区在线观看 | 大片免免费观看视频播放网站 | 亚洲欧美自拍视频 | 国产图片区| 日本三级黄色片网站 | 亚洲精品一区二区三区四 | 国产无套普通话对白 | 性刺激欧美三级在线观看 | 噜噜噜福利视频在线观看 |