前端宏任務、微任務、Dom 渲染的順序

1.瀏覽器包含多個進程

  • 1.主進程
    協(xié)調(diào)控制其他子進程(創(chuàng)建、銷毀)
  • 2.第三方插件進程
    每種類型的插件對應一個進程,僅當使用該插件時才創(chuàng)建
  • 3.GPU 進程
    用于 3D 繪制等
  • 4.渲染進程,就是我們說的瀏覽器內(nèi)核(最重要)
    負責頁面渲染,腳本執(zhí)行,事件處理等
    每個 tab 頁一個渲染進程

2.渲染進程包含了多個線程:

  • 1.JS 引擎線程
    負責處理解析和執(zhí)行 javascript 腳本程序
    只有一個 JS 引擎線程(單線程)
    與 GUI 渲染線程互斥,防止渲染結果不可預期
  • 2.GUI 渲染線程
    負責渲染頁面,布局和繪制
    頁面需要重繪和回流時,該線程就會執(zhí)行
    與 js 引擎線程互斥,防止渲染結果不可預期
  • 3.http 請求線程
    瀏覽器有一個單獨的線程用于處理 AJAX 請求
  • 4.事件處理線程(鼠標點擊、ajax 等)
    用來控制事件循環(huán)(鼠標點擊、setTimeout、ajax 等)
  • 5.定時器觸發(fā)線程
    setInterval 與 setTimeout 所在的線程

3. 為什么 JS 引擎線程和 GUI 渲染線程是互斥的?

JavaScript 是可操縱 DOM 的,如果在修改這些元素屬性同時渲染界面,那么渲染線程前后獲得的元素數(shù)據(jù)就可能不一致了。因此為了防止渲染出現(xiàn)不可預期的結果,瀏覽器設置 GUI 渲染線程與 JS 引擎為互斥的關系,當 JS 引擎執(zhí)行時 GUI 線程會被掛起,GUI 更新則會被保存在一個隊列中等到 JS 引擎線程空閑時立即被執(zhí)行。

4. 為什么 JS 會阻塞頁面加載?

從上面的互斥關系可以推導出,JS 如果執(zhí)行時間過長就會阻塞頁面。譬如,假設 JS 引擎正在進行巨量的計算,此時就算 GUI 有更新,也會被保存到隊列中,等待 JS 引擎空閑后執(zhí)行。然后,由于巨量計算,所以 JS 引擎很可能很久很久后才能空閑,自然會感覺到巨卡無比。所以,要盡量避免 JS 執(zhí)行時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞的感覺。

5. JS 引擎線程和 GUI 渲染線程是互斥的,那先后順序呢?

把下面三段代碼放到瀏覽器的控制臺執(zhí)行:

document.body.style = "background:black";
document.body.style = "background:red";
document.body.style = "background:blue";
document.body.style = "background:grey";
  • 結果:背景直接變成灰色
  • 分析:Call Stack 清空的時候,執(zhí)行,執(zhí)行到了 document.body.style = 'background:grey';這時,前面的代碼都被覆蓋了,此時 dom 渲染,背景色是灰色
document.body.style = "background:blue";
console.log(1);
Promise.resolve().then(function () {
  console.log(2);
  document.body.style = "background:black";
});
console.log(3);
  • 結果:背景直接變成黑色
  • 分析:document.body.style = 'background:blue'是同步代碼,document.body.style = 'background:black'是微任務,此時微任務執(zhí)行完,才會進行 dom 渲染,所以背景色是黑色
document.body.style = "background:blue";
setTimeout(function () {
  document.body.style = "background:black";
}, 0);
  • 結果:背景先一閃而過藍色,然后變成黑色
  • 分析:document.body.style = 'background:blue';是同步代碼,document.body.style = 'background:black'是宏任務,所以 dom 在同步代碼執(zhí)行完,宏任務執(zhí)行之前會渲染一次。然后宏任務執(zhí)行完又會渲染一次。2 次渲染,所以才會呈現(xiàn)背景先一閃而過藍色,然后變成黑色,這種效果。

總結:

1.先把Call Stack清空
2.然后執(zhí)行當前的微任務
3.接下來DOM渲染
微任務在dom渲染之前執(zhí)行,宏任務在dom渲染之后執(zhí)行。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容