摘要:定時(shí)器線程由于是單線程運(yùn)行,所以不能抽出時(shí)間來(lái)計(jì)時(shí),只能另開(kāi)辟一個(gè)線程來(lái)處理定時(shí)器任務(wù),等計(jì)時(shí)完成,把定時(shí)器要執(zhí)行的操作添加到事件任務(wù)隊(duì)列尾,等待引擎線程來(lái)處理。已經(jīng)知道了是單線程運(yùn)行的,也知道中有同步操作和異步操作。
js運(yùn)行機(jī)制
本章了解一下js的運(yùn)行原理,了解了js的運(yùn)行原理才能寫(xiě)出更優(yōu)美的代碼,提高運(yùn)行效率,還能解決開(kāi)發(fā)中遇到的不理解的問(wèn)題。進(jìn)程與線程
進(jìn)程是cpu資源分配的最小單位,進(jìn)程可以包含多個(gè)線程。 瀏覽器就是多進(jìn)程的,每打開(kāi)的一個(gè)瀏覽器窗口就是一個(gè)進(jìn)程。
線程是cpu調(diào)度的最小單位,同一進(jìn)程下的各個(gè)線程之間共享程序的內(nèi)存空間。
可以把進(jìn)程看做一個(gè)倉(cāng)庫(kù),線程是可以運(yùn)輸?shù)呢涇?chē),每個(gè)倉(cāng)庫(kù)有屬于自己的多輛貨車(chē)為倉(cāng)庫(kù)服務(wù)(運(yùn)貨),每個(gè)倉(cāng)庫(kù)可以同時(shí)由多輛車(chē)同時(shí)拉貨,但是每輛車(chē)同一時(shí)間只能干一件事,就是運(yùn)輸本次的貨物。這樣就好理解了吧。
渲染進(jìn)程瀏覽器包括4個(gè)進(jìn)程:
主進(jìn)程(Browser進(jìn)程),瀏覽器只有一個(gè)主進(jìn)程,負(fù)責(zé)資源下載,界面展示等主要基礎(chǔ)功能
GPU進(jìn)程,負(fù)責(zé)3D圖示繪制
第三方插件進(jìn)程,負(fù)責(zé)第三方插件處理
渲染進(jìn)程(Renderer進(jìn)程),負(fù)責(zé)js執(zhí)行,頁(yè)面渲染等功能,也是本章重點(diǎn)內(nèi)容
渲染進(jìn)程主要包括GUI渲染線程、Js引擎線程、事件循環(huán)線程、定時(shí)器線程、http異步線程。
GUI渲染線程先看看瀏覽器得到一個(gè)網(wǎng)站資源后干了哪些事:
首先瀏覽器會(huì)解析html代碼(實(shí)際上html代碼本質(zhì)是字符串)轉(zhuǎn)化為瀏覽器認(rèn)識(shí)的節(jié)點(diǎn),生成DOM樹(shù),也就是DOM Tree
然后解析css,生成CSSOM(CSS規(guī)則樹(shù))
把DOM Tree 和CSSOM結(jié)合,生成Rendering Tree(渲染樹(shù))
GUI就是來(lái)干這個(gè)事情的,如果修改了一些元素的顏色或者背景色,頁(yè)面就會(huì)重繪(Repaint),如果修改元素的尺寸,頁(yè)面就會(huì)回流(Reflow),當(dāng)頁(yè)面需要Repaing和Reflow時(shí)GUI多會(huì)執(zhí)行,進(jìn)行頁(yè)面繪制。
這里提示一點(diǎn):Reflow比Repaint的成本更高,在js性能優(yōu)化中會(huì)將如何避免Reflow和Repaint
JS引擎線程js引擎線程就是js內(nèi)核,負(fù)責(zé)解析與執(zhí)行js代碼,也稱為主線程。瀏覽器同時(shí)只能有一個(gè)JS引擎線程在運(yùn)行JS程序,所以js是單線程運(yùn)行的。
需要注意的是,js引擎線程和GUI渲染線程同時(shí)只能有一個(gè)工作,js引擎線程會(huì)阻塞GUI渲染線程
adiv2
在瀏覽器渲染的時(shí)候遇到
這是網(wǎng)絡(luò)上對(duì)Event Loop的解釋圖,相信大家現(xiàn)在能明白這張圖的含義了。
有關(guān)定時(shí)器(setTimeout、setInterval)的更多趣事 定時(shí)器會(huì)按照規(guī)定時(shí)間執(zhí)行嗎?定時(shí)器是規(guī)定在一段時(shí)間之后執(zhí)行一段代碼,但是在js執(zhí)行中不會(huì)準(zhǔn)確無(wú)誤的按照預(yù)期的時(shí)間去執(zhí)行定時(shí)器里面的代碼。
一個(gè)原因是W3C標(biāo)準(zhǔn)規(guī)定setTimeout中最小的時(shí)間周期是4毫秒,凡是低于4ms的時(shí)間間隔都按照4ms來(lái)處理。
其實(shí)還有一個(gè)重要的原因,如果仔細(xì)看上面的文章,大家應(yīng)該會(huì)想到在js執(zhí)行的時(shí)候,主線程碰到定時(shí)器的時(shí)候,是不會(huì)直接處理的,應(yīng)該是先把定時(shí)器事件交給定時(shí)器線程去處理,這時(shí)主線程繼續(xù)執(zhí)行下面的代碼,同時(shí)定時(shí)器線程開(kāi)始計(jì)時(shí)處理,等到計(jì)時(shí)完畢,事件循環(huán)線程會(huì)把定時(shí)器要執(zhí)行的操作放在事件隊(duì)列末尾,等主線程空閑的時(shí)候再來(lái)執(zhí)行事件隊(duì)列里面的操作。
應(yīng)該使用setTimeout還是setInterval使用setTimeout模擬setInterval代碼類似以下代碼:
var say = function() { setTimeout(say, 1000) console.log("hello world") } setTimeout(say, 1000)
這樣js碰到定時(shí)器,會(huì)交給定時(shí)器線程處理,然后等計(jì)時(shí)完畢,定時(shí)器里面的操作添加到事件隊(duì)列,等主線程空閑去執(zhí)行,主線程執(zhí)行的時(shí)候又會(huì)發(fā)遇到定時(shí)器,這是又開(kāi)始執(zhí)行上面的一系列操作。
你會(huì)發(fā)現(xiàn),這樣做會(huì)在每一次定時(shí)器執(zhí)行完畢才開(kāi)始下一個(gè)定時(shí)器,其中的誤差只是等待主線程空閑所需要等待的時(shí)間。
而setInterval是規(guī)定每隔固定的時(shí)間就往定時(shí)器線程中推入一個(gè)事件,這樣做有一個(gè)問(wèn)題,就是累積效應(yīng)。
累積效應(yīng):就是如果定時(shí)器里面的代碼執(zhí)行所需的時(shí)間大于定時(shí)器的執(zhí)行周期,就會(huì)出現(xiàn)累計(jì)效應(yīng),簡(jiǎn)單來(lái)說(shuō)就是上一次定時(shí)器里面的操作還沒(méi)執(zhí)行完畢,下一次定時(shí)器事件又來(lái)了
累積效應(yīng)會(huì)導(dǎo)致有些事件丟失,具體為什么會(huì)丟失,感興趣的可以看這篇文章,所以為了保險(xiǎn)起見(jiàn),盡量去使用setTimeout而不使用setInterval。
如果有對(duì)setTimeout非常感興趣的同學(xué),我非常推薦大家去看看80% 應(yīng)聘者都不及格的 JS 面試題這篇文章。
macrotask與microtaskmicrotask是Promise里一個(gè)新的概念。
macrotaskmacrotask中的事件都是放在一個(gè)事件隊(duì)列中的,而這個(gè)隊(duì)列由事件觸發(fā)線程維護(hù)
macrotask(又稱之為宏任務(wù)),可以理解是每次執(zhí)行棧執(zhí)行的代碼就是一個(gè)宏任務(wù)(包括每次從事件隊(duì)列中獲取一個(gè)事件回調(diào)并放到執(zhí)行棧中執(zhí)行)
每一個(gè)task會(huì)從頭到尾將這個(gè)任務(wù)執(zhí)行完畢,不會(huì)執(zhí)行其它
瀏覽器為了能夠使得JS內(nèi)部task與DOM任務(wù)能夠有序的執(zhí)行,會(huì)在一個(gè)task執(zhí)行結(jié)束后,在下一個(gè) task 執(zhí)行開(kāi)始前,對(duì)頁(yè)面進(jìn)行重新渲染
microtaskmicrotask(又稱為微任務(wù)),可以理解是在當(dāng)前 task 執(zhí)行結(jié)束后立即執(zhí)行的任務(wù)
microtask中的所有微任務(wù)都是添加到微任務(wù)隊(duì)列(Job Queues)中,等待當(dāng)前macrotask執(zhí)行完畢后執(zhí)行,而這個(gè)隊(duì)列由JS引擎線程維護(hù)
在當(dāng)前task任務(wù)后,下一個(gè)task之前,在渲染之前執(zhí)行
所以它的響應(yīng)速度相比setTimeout(setTimeout是task)會(huì)更快,因?yàn)闊o(wú)需等渲染
也就是說(shuō),在某一個(gè)macrotask執(zhí)行完后,就會(huì)將在它執(zhí)行期間產(chǎn)生的所有microtask都執(zhí)行完畢(在渲染前)
請(qǐng)看網(wǎng)絡(luò)盜圖:
所以js運(yùn)行過(guò)程:
執(zhí)行一個(gè)宏任務(wù)(棧中沒(méi)有就從事件隊(duì)列中獲取)
執(zhí)行過(guò)程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中
宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
當(dāng)前宏任務(wù)執(zhí)行完畢,開(kāi)始檢查渲染,然后GUI線程接管渲染
渲染完畢后,JS線程繼續(xù)接管,開(kāi)始下一個(gè)宏任務(wù)(從事件隊(duì)列中獲取)
有關(guān)macrotask和microtask的分析借鑒于從瀏覽器多進(jìn)程到JS單線程,JS運(yùn)行機(jī)制最全面的一次梳理
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107200.html
摘要:定時(shí)器線程由于是單線程運(yùn)行,所以不能抽出時(shí)間來(lái)計(jì)時(shí),只能另開(kāi)辟一個(gè)線程來(lái)處理定時(shí)器任務(wù),等計(jì)時(shí)完成,把定時(shí)器要執(zhí)行的操作添加到事件任務(wù)隊(duì)列尾,等待引擎線程來(lái)處理。已經(jīng)知道了是單線程運(yùn)行的,也知道中有同步操作和異步操作。 js運(yùn)行機(jī)制 本章了解一下js的運(yùn)行原理,了解了js的運(yùn)行原理才能寫(xiě)出更優(yōu)美的代碼,提高運(yùn)行效率,還能解決開(kāi)發(fā)中遇到的不理解的問(wèn)題。 進(jìn)程與線程 進(jìn)程是cpu資源分配的...
摘要:定時(shí)器線程由于是單線程運(yùn)行,所以不能抽出時(shí)間來(lái)計(jì)時(shí),只能另開(kāi)辟一個(gè)線程來(lái)處理定時(shí)器任務(wù),等計(jì)時(shí)完成,把定時(shí)器要執(zhí)行的操作添加到事件任務(wù)隊(duì)列尾,等待引擎線程來(lái)處理。已經(jīng)知道了是單線程運(yùn)行的,也知道中有同步操作和異步操作。 js運(yùn)行機(jī)制 本章了解一下js的運(yùn)行原理,了解了js的運(yùn)行原理才能寫(xiě)出更優(yōu)美的代碼,提高運(yùn)行效率,還能解決開(kāi)發(fā)中遇到的不理解的問(wèn)題。 進(jìn)程與線程 進(jìn)程是cpu資源分配的...
摘要:實(shí)現(xiàn)的四大模塊上文簡(jiǎn)述了源碼的大體框架結(jié)構(gòu),接下來(lái)我們來(lái)實(shí)現(xiàn)一個(gè)的框架,筆者認(rèn)為理解和實(shí)現(xiàn)一個(gè)框架需要實(shí)現(xiàn)四個(gè)大模塊,分別是封裝創(chuàng)建類構(gòu)造函數(shù)構(gòu)造對(duì)象中間件機(jī)制和剝洋蔥模型的實(shí)現(xiàn)錯(cuò)誤捕獲和錯(cuò)誤處理下面我們就逐一分析和實(shí)現(xiàn)。 什么是koa框架? ? ? ? ?koa是一個(gè)基于node實(shí)現(xiàn)的一個(gè)新的web框架,它是由express框架的原班人馬打造的。它的特點(diǎn)是優(yōu)雅、簡(jiǎn)潔、表達(dá)力強(qiáng)、自由度...
摘要:實(shí)現(xiàn)的四大模塊上文簡(jiǎn)述了源碼的大體框架結(jié)構(gòu),接下來(lái)我們來(lái)實(shí)現(xiàn)一個(gè)的框架,筆者認(rèn)為理解和實(shí)現(xiàn)一個(gè)框架需要實(shí)現(xiàn)四個(gè)大模塊,分別是封裝創(chuàng)建類構(gòu)造函數(shù)構(gòu)造對(duì)象中間件機(jī)制和剝洋蔥模型的實(shí)現(xiàn)錯(cuò)誤捕獲和錯(cuò)誤處理下面我們就逐一分析和實(shí)現(xiàn)。 什么是koa框架? ? ? ? ?koa是一個(gè)基于node實(shí)現(xiàn)的一個(gè)新的web框架,它是由express框架的原班人馬打造的。它的特點(diǎn)是優(yōu)雅、簡(jiǎn)潔、表達(dá)力強(qiáng)、自由度...
閱讀 2955·2023-04-25 19:20
閱讀 819·2021-11-24 09:38
閱讀 2074·2021-09-26 09:55
閱讀 2447·2021-09-02 15:11
閱讀 2087·2019-08-30 15:55
閱讀 3625·2019-08-30 15:54
閱讀 3164·2019-08-30 14:03
閱讀 2975·2019-08-29 17:11