LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

事件循環(huán)

freeflydom
2024年3月25日 15:2 本文熱度 1016

瀏覽器的進程模型

何為進程?

程序運行需要有它自己專屬的內(nèi)存空間,可以把這塊內(nèi)存空間簡單的理解為進程

每個應(yīng)用至少有一個進程,進程之間相互獨立,即使要通信,也需要雙方同意。

何為線程?

有了進程后,就可以運行程序的代碼了。

運行代碼的「人」稱之為「線程」。

一個進程至少有一個線程,所以在進程開啟后會自動創(chuàng)建一個線程來運行代碼,該線程稱之為主線程。

如果程序需要同時執(zhí)行多塊代碼,主線程就會啟動更多的線程來執(zhí)行代碼,所以一個進程中可以包含多個線程。

瀏覽器有哪些進程和線程?

瀏覽器是一個多進程多線程的應(yīng)用程序

瀏覽器內(nèi)部工作極其復(fù)雜。

為了避免相互影響,為了減少連環(huán)崩潰的幾率,當啟動瀏覽器后,它會自動啟動多個進程。

可以在瀏覽器的任務(wù)管理器中查看當前的所有進程

其中,最主要的進程有:

  1. 瀏覽器進程

    主要負責界面顯示、用戶交互、子進程管理等。瀏覽器進程內(nèi)部會啟動多個線程處理不同的任務(wù)。

  2. 網(wǎng)絡(luò)進程

    負責加載網(wǎng)絡(luò)資源。網(wǎng)絡(luò)進程內(nèi)部會啟動多個線程來處理不同的網(wǎng)絡(luò)任務(wù)。

  3. 渲染進程(本節(jié)課重點講解的進程)

    渲染進程啟動后,會開啟一個渲染主線程,主線程負責執(zhí)行 HTML、CSS、JS 代碼。

    默認情況下,瀏覽器會為每個標簽頁開啟一個新的渲染進程,以保證不同的標簽頁之間不相互影響。

    將來該默認模式可能會有所改變,有興趣的同學可參見chrome官方說明文檔

渲染主線程是如何工作的?

渲染主線程是瀏覽器中最繁忙的線程,需要它處理的任務(wù)包括但不限于:

  • 解析 HTML

  • 解析 CSS

  • 計算樣式

  • 布局

  • 處理圖層

  • 每秒把頁面畫 60 次

  • 執(zhí)行全局 JS 代碼

  • 執(zhí)行事件處理函數(shù)

  • 執(zhí)行計時器的回調(diào)函數(shù)

  • ......

思考題:為什么渲染進程不適用多個線程來處理這些事情?

要處理這么多的任務(wù),主線程遇到了一個前所未有的難題:如何調(diào)度任務(wù)?

比如:

  • 我正在執(zhí)行一個 JS 函數(shù),執(zhí)行到一半的時候用戶點擊了按鈕,我該立即去執(zhí)行點擊事件的處理函數(shù)嗎?

    • 不會,得先把手里的任務(wù)做完后,再從隊列里面拿

  • 我正在執(zhí)行一個 JS 函數(shù),執(zhí)行到一半的時候某個計時器到達了時間,我該立即去執(zhí)行它的回調(diào)嗎?

  • 瀏覽器進程通知我“用戶點擊了按鈕”,與此同時,某個計時器也到達了時間,我應(yīng)該處理哪一個呢?

  • ......

渲染主線程想出了一個絕妙的主意來處理這個問題:排隊

  1. 在最開始的時候,渲染主線程會進入一個無限循環(huán)

  2. 每一次循環(huán)會檢查消息隊列中是否有任務(wù)存在。如果有,就取出第一個任務(wù)執(zhí)行,執(zhí)行完一個后進入下一次循環(huán);如果沒有,則進入休眠狀態(tài)。

  3. 其他所有線程(包括其他進程的線程)可以隨時向消息隊列添加任務(wù)。新任務(wù)會加到消息隊列的末尾。在添加新任務(wù)時,如果主線程是休眠狀態(tài),則會將其喚醒以繼續(xù)循環(huán)拿取任務(wù)

這樣一來,就可以讓每個任務(wù)有條不紊的、持續(xù)的進行下去了。

整個過程,被稱之為事件循環(huán)(消息循環(huán))

若干解釋

何為異步?

代碼在執(zhí)行過程中,會遇到一些無法立即處理的任務(wù),比如:

  • 計時完成后需要執(zhí)行的任務(wù) —— setTimeoutsetInterval

  • 網(wǎng)絡(luò)通信完成后需要執(zhí)行的任務(wù) -- XHRFetch

  • 用戶操作后需要執(zhí)行的任務(wù) -- addEventListener

如果讓渲染主線程等待這些任務(wù)的時機達到,就會導(dǎo)致主線程長期處于「阻塞」的狀態(tài),從而導(dǎo)致瀏覽器「卡死」

渲染主線程承擔著極其重要的工作,無論如何都不能阻塞!

因此,瀏覽器選擇**異步**來解決這個問題

使用異步的方式,渲染主線程永不阻塞

面試題:如何理解 JS 的異步?

參考答案:

JS是一門單線程的語言,這是因為它運行在瀏覽器的渲染主線程中,而渲染主線程只有一個。

而渲染主線程承擔著諸多的工作,渲染頁面、執(zhí)行 JS 都在其中運行。

如果使用同步的方式,就極有可能導(dǎo)致主線程產(chǎn)生阻塞,從而導(dǎo)致消息隊列中的很多其他任務(wù)無法得到執(zhí)行。這樣一來,一方面會導(dǎo)致繁忙的主線程白白的消耗時間,另一方面導(dǎo)致頁面無法及時更新,給用戶造成卡死現(xiàn)象。

所以瀏覽器采用異步的方式來避免。具體做法是當某些任務(wù)發(fā)生時,比如計時器、網(wǎng)絡(luò)、事件監(jiān)聽,主線程將任務(wù)交給其他線程去處理,自身立即結(jié)束任務(wù)的執(zhí)行,轉(zhuǎn)而執(zhí)行后續(xù)代碼。當其他線程完成時,將事先傳遞的回調(diào)函數(shù)包裝成任務(wù),加入到消息隊列的末尾排隊,等待主線程調(diào)度執(zhí)行。

在這種異步模式下,瀏覽器永不阻塞,從而最大限度的保證了單線程的流暢運行。

JS為何會阻礙渲染?

先看代碼

<h1>Mr.Yuan is awesome!</h1>

<button>change</button>

<script>

  var h1 = document.querySelector('h1');

  var btn = document.querySelector('button');


  // 死循環(huán)指定的時間

  function delay(duration) {

    var start = Date.now();

    while (Date.now() - start < duration) {}

  }


  btn.onclick = function () {

    h1.textContent = '袁老師很帥!';

    delay(3000);

  };

</script>

點擊按鈕后,會發(fā)生什么呢?

三秒鐘內(nèi)之后才h1內(nèi)容變更為袁老師很帥!;為啥不是立即變更呢?因為h1.textContent的內(nèi)容確實變更了,但是渲染到頁面需要繪制,繪制任務(wù)也會被放到隊列中,但是在繪制之前還有個delay(3000),然后才是繪制。

任務(wù)有優(yōu)先級嗎?

任務(wù)沒有優(yōu)先級,在消息隊列中先進先出

消息隊列是有優(yōu)先級的

根據(jù) W3C 的最新解釋:

  • 每個任務(wù)都有一個任務(wù)類型,同一個類型的任務(wù)必須在一個隊列,不同類型的任務(wù)可以分屬于不同的隊列。 在一次事件循環(huán)中,瀏覽器可以根據(jù)實際情況從不同的隊列中取出任務(wù)執(zhí)行。

  • 瀏覽器必須準備好一個微隊列,微隊列中的任務(wù)優(yōu)先所有其他任務(wù)執(zhí)行 html.spec.whatwg.org/multipage/w…

隨著瀏覽器的復(fù)雜度急劇提升,W3C 不再使用宏隊列的說法

在目前 chrome 的實現(xiàn)中,至少包含了下面的隊列:

  • 延時隊列:用于存放計時器到達后的回調(diào)任務(wù),優(yōu)先級「中」

  • 交互隊列:用于存放用戶操作后產(chǎn)生的事件處理任務(wù),優(yōu)先級「高」

  • 微隊列:用戶存放需要最快執(zhí)行的任務(wù),優(yōu)先級「最高」

添加任務(wù)到微隊列的主要方式主要是使用 PromiseMutationObserver

例如:

// 立即把一個函數(shù)添加到微隊列 
Promise.resolve().then(函數(shù))

瀏覽器還有很多其他的隊列,由于和我們開發(fā)關(guān)系不大,不作考慮

面試題:闡述一下 JS 的事件循環(huán)

參考答案:

事件循環(huán)又叫做消息循環(huán),是瀏覽器渲染主線程的工作方式。

在 Chrome 的源碼中,它開啟一個不會結(jié)束的 for 循環(huán),每次循環(huán)從消息隊列中取出第一個任務(wù)執(zhí)行,而其他線程只需要在合適的時候?qū)⑷蝿?wù)加入到隊列末尾即可。

過去把消息隊列簡單分為宏隊列和微隊列,這種說法目前已無法滿足復(fù)雜的瀏覽器環(huán)境,取而代之的是一種更加靈活多變的處理方式。

根據(jù) W3C 官方的解釋,每個任務(wù)有不同的類型,同類型的任務(wù)必須在同一個隊列,不同的任務(wù)可以屬于不同的隊列。不同任務(wù)隊列有不同的優(yōu)先級,在一次事件循環(huán)中,由瀏覽器自行決定取哪一個隊列的任務(wù)。但瀏覽器必須有一個微隊列,微隊列的任務(wù)一定具有最高的優(yōu)先級,必須優(yōu)先調(diào)度執(zhí)行。

面試題:JS 中的計時器能做到精確計時嗎?為什么?

參考答案:

不行,因為:

  1. 計算機硬件沒有原子鐘,無法做到精確計時

  2. 操作系統(tǒng)的計時函數(shù)本身就有少量偏差,由于 JS 的計時器最終調(diào)用的是操作系統(tǒng)的函數(shù),也就攜帶了這些偏差

  3. 按照 W3C 的標準,瀏覽器實現(xiàn)計時器時,如果嵌套層級超過 5 層,則會帶有 4 毫秒的最少時間,這樣在計時時間少于 4 毫秒時又帶來了偏差

  4. 受事件循環(huán)的影響,計時器的回調(diào)函數(shù)只能在主線程空閑時運行,因此又帶來了偏差


作者:Geek喜多川海夢
鏈接:https://juejin.cn/post/7350103757402964003
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



該文章在 2024/3/25 15:02:54 編輯過
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
中文字幕无线码永久免费2020 | 亚洲激情一区二区 | 五月天婷婷在线亚洲综合一页 | 一级少妇女片完整版免费 | 制服中文在线永久 | 亚洲日韩Av一区二区三区中文 |