瀏覽器的渲染進(jìn)程的線程總共有五種:
(1)GUI渲染線程 負(fù)責(zé)渲染瀏覽器頁面,解析HTML、CSS,構(gòu)建DOM樹、構(gòu)建CSSOM樹、構(gòu)建渲染樹和繪制頁面;當(dāng)界面需要重繪或由于某種操作引發(fā)回流時,該線程就會執(zhí)行。
注意:GUI渲染線程和JS引擎線程是互斥的,當(dāng)JS引擎執(zhí)行時GUI線程會被掛起,GUI更新會被保存在一個隊(duì)列中等到JS引擎空閑時立即被執(zhí)行。
(2)JS引擎線程 JS引擎線程也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序,解析Javascript腳本,運(yùn)行代碼;JS引擎線程一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理,一個Tab頁中無論什么時候都只有一個JS引擎線程在運(yùn)行JS程序;
注意:GUI渲染線程與JS引擎線程的互斥關(guān)系,所以如果JS執(zhí)行的時間過長,會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞。
(3)時間觸發(fā)線程時間觸發(fā)線程屬于瀏覽器而不是JS引擎,用來控制事件循環(huán);當(dāng)JS引擎執(zhí)行代碼塊如setTimeOut時(也可是來自瀏覽器內(nèi)核的其他線程,如鼠標(biāo)點(diǎn)擊、AJAX異步請求等),會將對應(yīng)任務(wù)添加到事件觸發(fā)線程中;當(dāng)對應(yīng)的事件符合觸發(fā)條件被觸發(fā)時,該線程會把事件添加到待處理隊(duì)列的隊(duì)尾,等待JS引擎的處理;
注意:由于JS的單線程關(guān)系,所以這些待處理隊(duì)列中的事件都得排隊(duì)等待JS引擎處理(當(dāng)JS引擎空閑時才會去執(zhí)行);
(4)定時器觸發(fā)進(jìn)程定時器觸發(fā)進(jìn)程即setInterval與setTimeout所在線程;瀏覽器定時計數(shù)器并不是由JS引擎計數(shù)的,因?yàn)镴S引擎是單線程的,如果處于阻塞線程狀態(tài)就會影響記計時的準(zhǔn)確性;因此使用單獨(dú)線程來計時并觸發(fā)定時器,計時完畢后,添加到事件隊(duì)列中,等待JS引擎空閑后執(zhí)行,所以定時器中的任務(wù)在設(shè)定的時間點(diǎn)不一定能夠準(zhǔn)時執(zhí)行,定時器只是在指定時間點(diǎn)將任務(wù)添加到事件隊(duì)列中;
注意:W3C在HTML標(biāo)準(zhǔn)中規(guī)定,定時器的定時時間不能小于4ms,如果是小于4ms,則默認(rèn)為4ms。
(5)異步http請求線程
XMLHttpRequest連接后通過瀏覽器新開一個線程請求;
檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將回調(diào)函數(shù)放入事件隊(duì)列中,等待JS引擎空閑后執(zhí)行;