亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

瀏覽器和Node.js是怎么樣設計EventLoop的

發布時間:2022-01-05 10:34:02 來源:億速云 閱讀:79 作者:小新 欄目:web開發

這篇文章主要介紹瀏覽器和Node.js是怎么樣設計EventLoop的,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

瀏覽器的 Event Loop

JavaScript 是用于實現網頁交互邏輯的,涉及到 dom 操作,如果多個線程同時操作需要做同步互斥的處理,為了簡化就設計成了單線程,但是如果單線程的話,遇到定時邏輯、網絡請求又會阻塞住。怎么辦呢?

可以加一層調度邏輯。把 JS 代碼封裝成一個個的任務,放在一個任務隊列中,主線程就不斷的取任務執行就好了。

每次取任務執行,都會創建新的調用棧。

瀏覽器和Node.js是怎么樣設計EventLoop的

其中,定時器、網絡請求其實都是在別的線程執行的,執行完了之后在任務隊列里放個任務,告訴主線程可以繼續往下執行了。

瀏覽器和Node.js是怎么樣設計EventLoop的

因為這些異步任務是在別的線程執行完,然后通過任務隊列通知下主線程,是一種事件機制,所以這個循環叫做 Event Loop。

這些在其他線程執行的異步任務包括定時器(setTimeout、setInterval),UI 渲染、網絡請求(XHR 或 fetch)。

但是,現在的 Event Loop 有個嚴重的問題,沒有優先級的概念,只是按照先后順序來執行,那如果有高優先級的任務就得不到及時的執行了。所以,得設計一套插隊機制。

那就搞一個高優先級的任務隊列就好了,每執行完一個普通任務,都去把所有高優先級的任務給執行完,之后再去執行普通任務。

瀏覽器和Node.js是怎么樣設計EventLoop的

有了插隊機制之后,高優任務就能得到及時的執行。

這就是現在瀏覽器的 Event Loop。

其中普通任務叫做 MacroTask(宏任務),高優任務叫做 MicroTask(微任務)。

宏任務包括:setTimeout、setInterval、requestAnimationFrame、Ajax、fetch、script 標簽的代碼。

微任務包括:Promise.then、MutationObserver、Object.observe。

怎么理解宏微任務的劃分呢?

定時器、網絡請求這種都是在別的線程跑完之后通知主線程的普通異步邏輯,所以都是宏任務。

而高優任務的這三種也很好理解,MutationObserver 和 Object.observe 都是監聽某個對象的變化的,變化是很瞬時的事情,肯定要馬上響應,不然可能又變了,Promise 是組織異步流程的,異步結束調用 then 也是很高優的。

這就是瀏覽器里的 Event Loop 的設計:設計 Loop 機制和 Task 隊列是為了支持異步,解決邏輯執行阻塞主線程的問題,設計 MicroTask 隊列的插隊機制是為了解決高優任務盡早執行的問題。

但是后來,JS 的執行環境不只是瀏覽器一種了,還有了 Node.js,它同樣也要解決這些問題,但是它設計出來的 Event Loop 更細致一些。

Node.js 的 Event loop

Node 是一個新的 JS 運行環境,它同樣要支持異步邏輯,包括定時器、IO、網絡請求,很明顯,也可以用 Event Loop 那一套來跑。

但是呢,瀏覽器那套 Event Loop 就是為瀏覽器設計的,對于做高性能服務器來說,那種設計還是有點粗糙了。

哪里粗糙呢?

瀏覽器的 Event Loop 只分了兩層優先級,一層是宏任務,一層是微任務。但是宏任務之間沒有再劃分優先級,微任務之間也沒有再劃分優先級。

而 Node.js 任務宏任務之間也是有優先級的,比如定時器 Timer 的邏輯就比 IO 的邏輯優先級高,因為涉及到時間,越早越準確;而 close 資源的處理邏輯優先級就很低,因為不 close 最多多占點內存等資源,影響不大。

于是就把宏任務隊列拆成了五個優先級:Timers、Pending、Poll、Check、Close。

瀏覽器和Node.js是怎么樣設計EventLoop的

解釋一下這五種宏任務:

Timers Callback: 涉及到時間,肯定越早執行越準確,所以這個優先級最高很容易理解。

Pending Callback:處理網絡、IO 等異常時的回調,有的 *niux 系統會等待發生錯誤的上報,所以得處理下。

Poll Callback:處理 IO 的 data,網絡的 connection,服務器主要處理的就是這個。

Check Callback:執行 setImmediate 的回調,特點是剛執行完 IO 之后就能回調這個。

Close Callback:關閉資源的回調,晚點執行影響也不到,優先級最低。

所以呢,Node.js 的 Event Loop 就是這樣跑的了:

瀏覽器和Node.js是怎么樣設計EventLoop的

還有一點不同要特別注意:

Node.js 的 Event Loop 并不是瀏覽器那種一次執行一個宏任務,然后執行所有的微任務,而是執行完一定數量的 Timers 宏任務,再去執行所有微任務,然后再執行一定數量的 Pending 的宏任務,然后再去執行所有微任務,剩余的 Poll、Check、Close 的宏任務也是這樣。(訂正:node 11 之前是這樣,node 11 之后改為了每個宏任務都執行所有微任務了)

為什么這樣呢?

其實按照優先級來看很容易理解:

假設瀏覽器里面的宏任務優先級是 1,所以是按照先后順序依次執行,也就是一個宏任務,所有的微任務,再一個宏任務,再所有的微任務。

瀏覽器和Node.js是怎么樣設計EventLoop的

而 Node.js 的 宏任務之間也是有優先級的,所以 Node.js 的 Event Loop 每次都是把當前優先級的所有宏任務跑完再去跑微任務,然后再跑下一個優先級的宏任務。

瀏覽器和Node.js是怎么樣設計EventLoop的

也就是是一定數量的 Timers 宏任務,再所有微任務,再一定數量的 Pending Callback 宏任務,再所有微任務這樣。

為什么說是一定數量呢?

因為如果某個階段宏任務太多,下個階段就一直執行不到了,所以有個上限的限制,剩余的下個 Event Loop 再繼續執行。

除了宏任務有優先級,微任務也劃分了優先級,多了一個 process.nextTick 的高優先級微任務,在所有的普通微任務之前來跑。

瀏覽器和Node.js是怎么樣設計EventLoop的

所以,Node.js 的 Event Loop 的完整流程就是這樣的:

  • Timers 階段:執行一定數量的定時器,也就是 setTimeout、setInterval 的 callback,太多的話留到下次執行

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

  • Pending 階段:執行一定數量的 IO 和網絡的異常回調,太多的話留到下次執行

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

  • Idle/Prepare 階段:內部用的一個階段

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

  • Poll 階段:執行一定數量的文件的 data 回調、網絡的 connection 回調,太多的話留到下次執行。如果沒有 IO 回調并且也沒有 timers、check 階段的回調要處理,就阻塞在這里等待 IO 事件

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

  • Check 階段:執行一定數量的 setImmediate 的 callback,太多的話留到下次執行。

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

  • Close 階段:執行一定數量的 close 事件的 callback,太多的話留到下次執行。

  • 微任務:執行所有 nextTick 的微任務,再執行其他的普通微任務

比起瀏覽器里的 Event Loop,明顯復雜了很多,但是經過我們之前的分析,也能夠理解:

Node.js 對宏任務做了優先級劃分,從高到低分別是 Timers、Pending、Poll、Check、Close 這 5 種,也對微任務做了劃分,也就是 nextTick 的微任務和其他微任務。執行流程是先執行完當前優先級的一定數量的宏任務(剩下的留到下次循環),然后執行 process.nextTick 的微任務,再執行普通微任務,之后再執行下個優先級的一定數量的宏任務。。這樣不斷循環。其中還有一個 Idle/Prepare 階段是給 Node.js 內部邏輯用的,不需要關心。

改變了瀏覽器 Event Loop 里那種一次執行一個宏任務的方式,可以讓高優先級的宏任務更早的得到執行,但是也設置了個上限,避免下個階段一直得不到執行。

還有一個特別要注意的點,就是 poll 階段:如果執行到 poll 階段,發現 poll 隊列為空并且 timers 隊列、check 隊列都沒有任務要執行,那么就阻塞的等在這里等 IO 事件,而不是空轉。 這點設計也是因為服務器主要是處理 IO 的,阻塞在這里可以更早的響應 IO。

完整的 Node.js 的 Event Loop 是這樣的:

瀏覽器和Node.js是怎么樣設計EventLoop的

對比下瀏覽器的 Event Loop:

瀏覽器和Node.js是怎么樣設計EventLoop的

兩個 JS 運行環境的 Event Loop 整體設計思路是差不多的,只不過 Node.js 的 Event Loop 對宏任務和微任務做了更細粒度的劃分,也很容易理解,畢竟 Node.js 面向的環境和瀏覽器不同,更重要的是服務端對性能的要求會更高。

總結

JavaScript 最早是用于寫網頁交互邏輯的,為了避免多線程同時修改 dom 的同步問題,設計成了單線程,又為了解決單線程的阻塞問題,加了一層調度邏輯,也就是 Loop 循環和 Task 隊列,把阻塞的邏輯放到其他線程跑,從而支持了異步。然后為了支持高優先級的任務調度,又引入了微任務隊列,這就是瀏覽器的 Event Loop 機制:每次執行一個宏任務,然后執行所有微任務。

Node.js 也是一個 JS 運行環境,想支持異步同樣要用 Event Loop,只不過服務端環境更復雜,對性能要求更高,所以 Node.js 對宏微任務都做了更細粒度的優先級劃分:

Node.js 里劃分了 5 種宏任務,分別是 Timers、Pending、Poll、Check、Close。又劃分了 2 種微任務,分別是 process.nextTick 的微任務和其他的微任務。

Node.js 的 Event Loop 流程是執行當前階段的一定數量的宏任務(剩余的到下個循環執行),然后執行所有微任務,一共有 Timers、Pending、Idle/Prepare、Poll、Check、Close 6 個階段。(訂正:node 11 之前是這樣,node 11 之后改為了每個宏任務都執行所有微任務了)

其中 Idle/Prepare 階段是 Node.js 內部用的,不用關心。

特別要注意的是 Poll 階段,如果執行到這里,poll 隊列為空并且 timers、check 隊列也為空,就一直阻塞在這里等待 IO,直到 timers、check 隊列有回調再繼續 loop。

Event Loop 是 JS 為了支持異步和任務優先級而設計的一套調度邏輯,針對瀏覽器、Node.js 等不同環境有不同的設計(主要是任務優先級的劃分粒度不同),Node.js 面對的環境更復雜、對性能要求更高,所以 Event Loop 設計的更復雜一些。

以上是“瀏覽器和Node.js是怎么樣設計EventLoop的”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

陆良县| 丰县| 镇平县| 密云县| 宝坻区| 乌什县| 会宁县| 宁夏| 北票市| 青冈县| 玉龙| 新安县| 库车县| 栾城县| 泗水县| 万山特区| 新巴尔虎左旗| 昔阳县| 荆门市| 达州市| 于田县| 台中市| 车险| 洪洞县| 辽阳县| 北安市| 苏尼特右旗| 韶山市| 砀山县| 抚顺市| 奉节县| 河南省| 锡林郭勒盟| 松江区| 沙湾县| 洪江市| 沙河市| 石门县| 麟游县| 滁州市| 贺州市|