成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入前端-徹底搞懂瀏覽器運(yùn)行機(jī)制

YPHP / 577人閱讀

摘要:當(dāng)這些異步任務(wù)發(fā)生的時(shí)候,它們將會(huì)被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到運(yùn)行時(shí)執(zhí)行線程空閑時(shí)候才會(huì)按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。

瀏覽器是多進(jìn)程的

Browser進(jìn)程:

瀏覽器的主進(jìn)程(負(fù)責(zé)協(xié)調(diào)、主控),只有一個(gè)。

負(fù)責(zé)瀏覽器界面顯示,與用戶交互。如前進(jìn),后退等

負(fù)責(zé)各個(gè)頁面的管理,創(chuàng)建和銷毀其他進(jìn)程

將Renderer進(jìn)程得到的內(nèi)存中的Bitmap,繪制到用戶界面上

網(wǎng)絡(luò)資源的管理,下載等

第三方插件進(jìn)程:

每種類型的插件對(duì)應(yīng)一個(gè)進(jìn)程,僅當(dāng)使用該插件時(shí)才創(chuàng)建

GPU進(jìn)程:

最多一個(gè),用于3D繪制等

瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核)(Renderer進(jìn)程,內(nèi)部是多線程的):

默認(rèn)每個(gè)Tab頁面一個(gè)進(jìn)程,互不影響。主要作用為
頁面渲染,腳本執(zhí)行,事件處理等

新建頁面都會(huì)開啟一個(gè)新的進(jìn)程

上面的進(jìn)程會(huì)輔助這個(gè)進(jìn)程的執(zhí)行,其中渲染進(jìn)程對(duì)頁面的影響最重要

怎么查看瀏覽器進(jìn)程情況

打開Chrome Shift+Esc;我們可以看到進(jìn)程情況,Chrome圖標(biāo)就是Browser主進(jìn)程

多線程優(yōu)缺點(diǎn)

避免單個(gè)page crash影響整個(gè)瀏覽器

避免第三方插件crash影響整個(gè)瀏覽器

多進(jìn)程充分利用多核優(yōu)勢

方便使用沙盒模型隔離插件等進(jìn)程,提高瀏覽器穩(wěn)定性

簡單點(diǎn)理解:如果瀏覽器是單進(jìn)程,那么某個(gè)Tab頁崩潰了,就影響了整個(gè)瀏覽器,體驗(yàn)有多差;同理如果是單進(jìn)程,插件崩潰了也會(huì)影響整個(gè)瀏覽器;而且多進(jìn)程還有其它的諸多優(yōu)勢,當(dāng)然內(nèi)存等資源消耗也會(huì)更大

重點(diǎn)是瀏覽器內(nèi)核(渲染進(jìn)程)該進(jìn)程有多個(gè)線程完成 GUI渲染線程

負(fù)責(zé)渲染瀏覽器界面,解析HTML,CSS,構(gòu)建DOM樹和RenderObject樹,布局和繪制等。
當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會(huì)執(zhí)行
注意,GUI渲染線程與JS引擎線程是互斥的,當(dāng)JS引擎執(zhí)行時(shí)GUI線程會(huì)被掛起(相當(dāng)于被凍結(jié)了),GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JS引擎空閑時(shí)立即被執(zhí)行。

JS引擎線程

也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序。(例如V8引擎)
JS引擎線程負(fù)責(zé)解析Javascript腳本,運(yùn)行代碼。
JS引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理,一個(gè)Tab頁(renderer進(jìn)程)中無論什么時(shí)候都只有一個(gè)JS線程在運(yùn)行JS程序
同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執(zhí)行的時(shí)間過長,這樣就會(huì)造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞。

事件觸發(fā)線程

歸屬于瀏覽器而不是JS引擎,用來控制事件循環(huán)(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協(xié)助)
當(dāng)JS引擎執(zhí)行代碼塊如setTimeOut時(shí)(也可來自瀏覽器內(nèi)核的其他線程,如鼠標(biāo)點(diǎn)擊、AJAX異步請(qǐng)求等),會(huì)將對(duì)應(yīng)任務(wù)添加到事件線程中
當(dāng)對(duì)應(yīng)的事件符合觸發(fā)條件被觸發(fā)時(shí),該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JS引擎的處理
注意,由于JS的單線程關(guān)系,所以這些待處理隊(duì)列中的事件都得排隊(duì)等待JS引擎處理(當(dāng)JS引擎空閑時(shí)才會(huì)去執(zhí)行)

定時(shí)觸發(fā)器線程

傳說中的setInterval與setTimeout所在線程
瀏覽器定時(shí)計(jì)數(shù)器并不是由JavaScript引擎計(jì)數(shù)的,(因?yàn)镴avaScript引擎是單線程的, 如果處于阻塞線程狀態(tài)就會(huì)影響記計(jì)時(shí)的準(zhǔn)確)
因此通過多帶帶線程來計(jì)時(shí)并觸發(fā)定時(shí)(計(jì)時(shí)完畢后,添加到事件隊(duì)列中,等待JS引擎空閑后執(zhí)行)
注意,W3C在HTML標(biāo)準(zhǔn)中規(guī)定,規(guī)定要求setTimeout中低于4ms的時(shí)間間隔算為4ms。

異步http請(qǐng)求線程

在XMLHttpRequest在連接后是通過瀏覽器新開一個(gè)線程請(qǐng)求
將檢測到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個(gè)回調(diào)再放入事件隊(duì)列中。再由JavaScript引擎執(zhí)行。

進(jìn)程間的通信過程

Browser進(jìn)程收到用戶請(qǐng)求,首先需要獲取頁面內(nèi)容(譬如通過網(wǎng)絡(luò)下載資源),隨后將該任務(wù)通過RendererHost接口傳遞給Render進(jìn)程

Renderer進(jìn)程的Renderer接口收到消息,簡單解釋后,交給渲染線程,然后開始渲染

渲染線程接收請(qǐng)求,加載網(wǎng)頁并渲染網(wǎng)頁,這其中可能需要Browser進(jìn)程獲取資源和需要GPU進(jìn)程來幫助渲染

當(dāng)然可能會(huì)有JS線程操作DOM(這樣可能會(huì)造成回流并重繪)

最后Render進(jìn)程將結(jié)果傳遞給Browser進(jìn)程

Browser進(jìn)程接到結(jié)果并將結(jié)果繪制出來

渲染進(jìn)程(瀏覽器內(nèi)核)線程的關(guān)系 GUI渲染線程與JS引擎線程互斥

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

JS阻塞頁面加載

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

WebWorker,JS的多線程

JavaScript引擎是單線程運(yùn)行的,JavaScript中耗時(shí)的I/O操作都被處理為異步操作,它們包括鍵盤、鼠標(biāo)I/O輸入輸出事件、窗口大小的resize事件、定時(shí)器(setTimeout、setInterval)事件、Ajax請(qǐng)求網(wǎng)絡(luò)I/O回調(diào)等。當(dāng)這些異步任務(wù)發(fā)生的時(shí)候,它們將會(huì)被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到JavaScript運(yùn)行時(shí)執(zhí)行線程空閑時(shí)候才會(huì)按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。

創(chuàng)建Worker時(shí),JS引擎向?yàn)g覽器申請(qǐng)開一個(gè)子線程(子線程是瀏覽器開的,完全受主線程控制,而且不能操作DOM)
JS引擎線程與worker線程間通過特定的方式通信(postMessage API,需要通過序列化對(duì)象來與線程交互特定的數(shù)據(jù))

//主線程 main.js
var worker = new Worker("worker.js");
worker.onmessage = function(event){
    // 主線程收到子線程的消息
};
// 主線程向子線程發(fā)送消息
worker.postMessage({
    type: "start",
    value: 12345
});

//web worker.js
onmessage = function(event){
   // 收到
};
postMessage({
    type: "debug",
    message: "Starting processing..."
});
瀏覽器渲染流程 拿到內(nèi)容

瀏覽器根據(jù) DNS 服務(wù)器得到域名的 IP 地址

向這個(gè) IP 的機(jī)器發(fā)送 HTTP 請(qǐng)求

服務(wù)器收到、處理并返回 HTTP 請(qǐng)求

瀏覽器得到返回內(nèi)容

解析內(nèi)容建立Rendering Tree 解析HTMl構(gòu)建dom

dom作用: HTMLDOM是HTML Document Object Model(文檔對(duì)象模型)的縮寫,HTML DOM則是專門適用于HTML/XHTML的文檔對(duì)象模型。熟悉軟件開發(fā)的人員可以將HTML DOM理解為網(wǎng)頁的API。它將網(wǎng)頁中的各個(gè)元素都看作一個(gè)個(gè)對(duì)象,從而使網(wǎng)頁中的元素也可以被計(jì)算機(jī)語言獲取或者編輯。

dom規(guī)定

整個(gè)文檔是一個(gè)文檔節(jié)點(diǎn)

每個(gè)HTML標(biāo)簽是一個(gè)元素節(jié)點(diǎn)

包含在HTML元素中的文本是文本節(jié)點(diǎn)

每一個(gè)HTML屬性是一個(gè)屬性節(jié)點(diǎn)(屬性節(jié)點(diǎn)是另一個(gè)層面的理解,在瀏覽器后臺(tái)打印的時(shí)候,不存在屬性節(jié)點(diǎn))

注釋屬于注釋節(jié)點(diǎn)

解析過程:瀏覽器會(huì)自動(dòng)把HTML文檔解析為一個(gè)“文檔對(duì)象模型”,即Document Object Model,簡稱DOM,這是一個(gè)樹形結(jié)構(gòu),樹根是Document對(duì)象,樹干是網(wǎng)頁的根元素,然后分出兩個(gè)枝丫,一個(gè)是,一個(gè)是,然后網(wǎng)頁上的其他標(biāo)簽就是這棵樹上的樹葉和樹枝了,通過這個(gè)結(jié)構(gòu),就可以查找和控制網(wǎng)頁上的任何一個(gè)元素了。因此,可以這么說,網(wǎng)頁上的任何元素都是Document對(duì)象的子對(duì)象。

解析CSS產(chǎn)生CSS規(guī)則樹,css是由多帶帶的下載線程異步下載的,本身不會(huì)阻塞Dom加載,它和DOM結(jié)構(gòu)比較像然后結(jié)合DOM生成RenderTree Javascript解析, 通過 DOM API 和 CSSOM API 來操作 DOM Tree 和 CSS Rule Tree。 布局render樹(Layout/reflow),負(fù)責(zé)各元素尺寸、位置的計(jì)算 繪制render樹(paint),繪制頁面像素信息 瀏覽器會(huì)將各層的信息發(fā)送給GPU,GPU會(huì)將各層合成(composite),顯示在屏幕上

渲染過程中的問題 DOMContentLoaded與onload

當(dāng) DOMContentLoaded 事件觸發(fā)時(shí),僅當(dāng)DOM加載完成,不包括樣式表,圖片

當(dāng) onload 事件觸發(fā)時(shí),頁面上所有的DOM,樣式表,腳本,圖片都已經(jīng)加載完成了。 (渲染完畢了)

DOMContentLoaded -> load

瀏覽器如果渲染過程中遇到JS文件怎么處理?

上面說過GUI渲染線程與JS引擎線程是互斥的,所以渲染過程中,如果遇到

沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,也就是說不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。

(延遲執(zhí)行)

defer 屬性表示延遲執(zhí)行引入的 JavaScript,即這段 JavaScript 加載時(shí) HTML 并未停止解析,這兩個(gè)過程是并行的。整個(gè) document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關(guān)),會(huì)執(zhí)行所有由 defer-script 加載的 JavaScript 代碼,然后觸發(fā) DOMContentLoaded 事件。

defer 與相比普通 script,有兩點(diǎn)區(qū)別:載入 JavaScript 文件時(shí)不阻塞 HTML 的解析,執(zhí)行階段被放到 HTML 標(biāo)簽解析完成之后。 在加載多個(gè)JS腳本的時(shí)候,async是無順序的加載,而defer是有順序的加載。

(異步下載)

async 屬性表示異步執(zhí)行引入的 JavaScript,與 defer 的區(qū)別在于,如果已經(jīng)加載好,就會(huì)開始執(zhí)行。也就是加載不阻塞,執(zhí)行會(huì)阻塞。

瀏覽器的回流與重繪 (Reflow & Repaint)

瀏覽器使用流式布局模型 (Flow Based Layout)。
有了RenderTree,我們就知道了所有節(jié)點(diǎn)的樣式,然后計(jì)算他們?cè)陧撁嫔系拇笮『臀恢?,最后把?jié)點(diǎn)繪制到頁面上。

回流

當(dāng)Render Tree中部分或全部元素的尺寸、結(jié)構(gòu)、或某些屬性發(fā)生改變時(shí),瀏覽器重新渲染部分或全部文檔的過程稱為回流。

頁面首次渲染

瀏覽器窗口大小發(fā)生改變

元素尺寸或位置發(fā)生改變

元素內(nèi)容變化(文字?jǐn)?shù)量或圖片大小等等)

元素字體大小變化

添加或者刪除可見的DOM元素

激活CSS偽類(例如::hover)

查詢某些屬性或調(diào)用某些方法

重繪

當(dāng)頁面中元素樣式的改變并不影響它在文檔流中的位置時(shí)(例如:color、background-color、visibility等),瀏覽器會(huì)將新樣式賦予給元素并重新繪制它,這個(gè)過程稱為重繪。

參考文章

https://segmentfault.com/a/11...

https://juejin.im/post/5a6547...

https://juejin.im/post/5ca0c0...

https://juejin.im/post/5a9923...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/54172.html

相關(guān)文章

  • 深入前端-徹底搞懂JS的運(yùn)行機(jī)制

    摘要:瀏覽器是多進(jìn)程的詳情看我上篇總結(jié)瀏覽器執(zhí)行機(jī)制的文章深入前端徹底搞懂瀏覽器運(yùn)行機(jī)制瀏覽器每打開一個(gè)標(biāo)簽頁,就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程。執(zhí)行異步操作事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。 最近看了很多關(guān)于JS運(yùn)行機(jī)制的文章,每篇都獲益匪淺,但各有不同,所以在這里對(duì)這幾篇文章里說的很精辟的地方做一個(gè)總結(jié),參考文章鏈接見最后。本文博客地址 了解進(jìn)程和線程 進(jìn)程是應(yīng)用...

    luckyw 評(píng)論0 收藏0
  • 深入前端-徹底搞懂JS的運(yùn)行機(jī)制

    摘要:瀏覽器是多進(jìn)程的詳情看我上篇總結(jié)瀏覽器執(zhí)行機(jī)制的文章深入前端徹底搞懂瀏覽器運(yùn)行機(jī)制瀏覽器每打開一個(gè)標(biāo)簽頁,就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程。執(zhí)行異步操作事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。 最近看了很多關(guān)于JS運(yùn)行機(jī)制的文章,每篇都獲益匪淺,但各有不同,所以在這里對(duì)這幾篇文章里說的很精辟的地方做一個(gè)總結(jié),參考文章鏈接見最后。本文博客地址 了解進(jìn)程和線程 進(jìn)程是應(yīng)用...

    jaysun 評(píng)論0 收藏0
  • 深入前端-徹底搞懂覽器運(yùn)行機(jī)制

    摘要:當(dāng)這些異步任務(wù)發(fā)生的時(shí)候,它們將會(huì)被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到運(yùn)行時(shí)執(zhí)行線程空閑時(shí)候才會(huì)按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。 瀏覽器是多進(jìn)程的 showImg(https://segmentfault.com/img/remote/1460000019706956?w=815&h=517); Browser進(jìn)程: 瀏覽器的主進(jìn)程(負(fù)責(zé)協(xié)調(diào)、主控),只有一個(gè)。 負(fù)...

    Youngs 評(píng)論0 收藏0
  • 徹底搞懂覽器Event-loop

    摘要:檢查宏任務(wù)隊(duì)列,發(fā)現(xiàn)有的回調(diào)函數(shù)立即執(zhí)行回調(diào)函數(shù)輸出。接著遇到它的作用是在后將回調(diào)函數(shù)放到宏任務(wù)隊(duì)列中這個(gè)任務(wù)在再下一次的事件循環(huán)中執(zhí)行。 為什么會(huì)寫這篇博文呢? 前段時(shí)間,和頭條的小伙伴聊天問頭條面試前端會(huì)問哪些問題,他稱如果是他面試的話,event-loop肯定是要問的。那天聊了蠻多,event-loop算是給我留下了很深的印象,原因很簡單,因?yàn)橹拔覐奈瓷钊肓私膺^,如果是面試的時(shí)...

    source 評(píng)論0 收藏0
  • 徹底搞懂JavaScript執(zhí)行機(jī)制

    摘要:徹底搞懂執(zhí)行機(jī)制首先我們大家都了解的是,是一門單線程語言,所以我們就可以得出是按照語句順序執(zhí)行的首先看這個(gè)顯然大家都知道結(jié)果,依次輸出,然而換一種這個(gè)時(shí)候再看代碼的順序執(zhí)行,輸出,,,。不過即使主線程為空,也是達(dá)不到的,根據(jù)標(biāo)準(zhǔn),最低是。 徹底搞懂JavaScript執(zhí)行機(jī)制 首先我們大家都了解的是,JavaScript 是一門單線程語言,所以我們就可以得出: JavaScript 是...

    hizengzeng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<