消息隊列和事件循環(Event Loop)

產生原因
為什麼會有消息隊列和事件循環呢?首先最關鍵的一點在於JS是個單執行緒,並且主執行緒非常繁忙,既要處理 DOM,又要計算樣式,還要處理布局,同時還需要處理 JavaScript 任務以及各種輸入事件。要讓這麼多不同類型的任務在主執行緒中有條不紊地執行,這就需要一個系統來統籌調度這些任務,這個統籌調度系統就是消息隊列和事件循環系統。
消息隊列
作用
消息隊列是一種數據結構,可以存放要執行的任務。它符合隊列「先進先出」的特點,也就是說要添加任務的話,添加到隊列的尾部;要取出任務的話,從隊列頭部去取。
事件循環
作用
在執行緒運行過程中,接收並執行新的任務,就需要採用事件循環機制。
消息隊列和事件循環的配合♻️
執行步驟
- 若有其他進程通訊則會通過IPC與IO執行緒進行消息傳遞,
- IO執行緒接收到其他進程傳進來的消息後,則會將其添加到消息隊列尾部;
- 渲染主執行緒循環地從消息隊列頭部中讀取任務,執行任務;
存在的問題
如何處理高優先順序任務?
添加了微任務隊列來解決,通常我們把消息隊列中的任務稱為宏任務,每個宏任務中都包含了一個微任務隊列,在執行宏任務的過程中,如果DOM有變化,那麼就會將該變化添加到微任務列表中,這樣就不會影響到宏任務的繼續執行,因此也就解決了執行效率的問題。等宏任務中的主要功能都直接完成之後,這時候,渲染引擎並不著急去執行下一個宏任務,而是執行當前宏任務中的微任務,因為 DOM 變化的事件都保存在這些微任務隊列中,這樣也就解決了實時性問題。
如何解決單個任務執行時長過久的問題?
JavaScript 可以通過回調功能來規避這種問題,也就是讓要執行的 JavaScript 任務滯後執行。
參考
瀏覽器工作原理與實踐