瀏覽器執行js原理
- 2020 年 3 月 9 日
- 筆記
在js任務循環機制中,為什麼會有宏任務與微任務之分?
是不是大都數前端開發者都會有這樣的疑惑,確實,我自己在開發的過程中每次碰到promise,setTimeout,requestAnimationFrame都會去想,在這個執行的過程中到底發生了什麼?
解析:
在前端執行一系列任務的時候,渲染進程會創建一個消息隊列,在這個消息隊列里存放著待執行的任務函數,按照先進先出的原則,依次執行任務函數。因此只要消息隊列里有任務,JS執行主執行緒就會不斷的執行消息隊列里的任務。這便是js單執行緒執行js程式碼的簡單原理,當然涉及的深的話,應該還要有IO執行緒,專門處理新加進來的任務,以及其它進程過來的任務。
但是js執行過程作為一個單執行緒的執行過程,其實是有缺點的。上面說過了,消息隊列是「先進先出」的屬性,也就是說放入隊列中的任務,需要等待前面的任務被執行完,才會被執行。鑒於這個屬性,那js是如何處理高優先順序的任務?
js是如何處理高優先順序的任務?
比如一個典型的場景,DOM節點的變化,增、刪,改,如果頁面上的一個輸入框狀態需要實時的映射到頁面上。一個通用的設計的是,利用 JavaScript 設計一套監聽介面,當變化發生時,渲染引擎同步調用這些介面,這是一個典型的觀察者模式,即給這個輸入框添加一個變化事件的監聽。
但是這個模式有一個問題,就是如果當前的DOM變化非常的頻繁,都去執行js任務的話,會導致當前在執行的js任務被延長,從而導致執行效率的下降;如果把這些任務添加到消息隊列的尾部,則無法及時響應用戶的操作。要想兼容這兩種情況,微任務便應運而生了。
通常我們把消息隊列中的任務稱為宏任務,每個宏任務中都包含了一個微任務隊列,在執行宏任務的過程中,如果 DOM 有變化,那麼就會將該變化添加到微任務列表中,這樣就不會影響到宏任務的繼續執行,因此也就解決了執行效率的問題。
等宏任務中的主要功能都直接完成之後,這時候,渲染引擎並不著急去執行下一個宏任務,而是執行當前宏任務中的微任務,因為 DOM 變化的事件都保存在這些微任務隊列中,這樣也就解決了實時性問題。
這便是在js執行過程中為什麼會有微任務與宏任務之分的原因。
文章轉自 瀏覽器執行js原理 , https://www.xiaye0.com/articlejs?id=40