背景
每一個(gè)頁面都有一個(gè)渲染主線程,會(huì)處理很多任務(wù),比如:DOM、樣式計(jì)算、布局等等。如此多的任務(wù)就需要一個(gè)消息隊(duì)列來進(jìn)行管理。這些任務(wù)的類型,就是我們通常所說的宏任務(wù)以及微任務(wù)。
兩種任務(wù)的關(guān)系,以及他們和UI線程渲染的關(guān)系
其實(shí)宏任務(wù)以及微任務(wù)的概念在前端已經(jīng)是很普及的了,相關(guān)文章鏈接。但是有以下幾個(gè)問題一直困擾著我:
- 宏任務(wù)以及微任務(wù)的關(guān)系
- 這兩種任務(wù)和GUI渲染線程的關(guān)系
所以研究總結(jié)如下關(guān)系:

截屏2021-03-17 上午8.49.58.png
宏任務(wù)和他所產(chǎn)生的微任務(wù)是綁定的,一個(gè)宏任務(wù)執(zhí)行完成后,這個(gè)宏任務(wù)所產(chǎn)生的微任務(wù),以及微任務(wù)產(chǎn)生的微任務(wù)全部執(zhí)行完后。才會(huì)執(zhí)行下一個(gè)宏任務(wù)。如果這些任務(wù)耗時(shí)不長,那么一幀16ms內(nèi),可以執(zhí)行多個(gè)宏任務(wù)。

截屏2021-03-17 上午8.49.01.png
如果一個(gè)宏任務(wù)以及宏任務(wù)產(chǎn)生的微任務(wù)耗時(shí)過長,超過16ms,那么就會(huì)造成UI線程渲染阻塞。其中如果一個(gè)宏任務(wù)耗時(shí)過長,也會(huì)等待其所產(chǎn)生的微任務(wù)執(zhí)行完成后再進(jìn)行UI線程渲染頁面。
為什么要分兩種任務(wù)?
每一個(gè)任務(wù)的執(zhí)行當(dāng)中,有可能會(huì)產(chǎn)生新的任務(wù),那么這些新的任務(wù)有兩種插入消息隊(duì)列的方式:

image (1).png
這也主要是宏任務(wù)和微任務(wù)的區(qū)別,在任務(wù)執(zhí)行過程中:
- 產(chǎn)生的宏任務(wù)直接插入消息隊(duì)列尾部依次執(zhí)行。
- 產(chǎn)生的微任務(wù)直接插入當(dāng)前任務(wù)的微任務(wù)隊(duì)列中,在此任務(wù)執(zhí)行完成后,直接執(zhí)行此任務(wù)的微任務(wù)隊(duì)列。
可以看出微任務(wù)的存在主要是保證任務(wù)執(zhí)行的時(shí)效性,而宏任務(wù)就是正常的直接插入消息隊(duì)列尾部。
總結(jié)
- 宏任務(wù)和微任務(wù)是綁定關(guān)系,宏任務(wù)執(zhí)行完成后會(huì)執(zhí)行它所產(chǎn)生的微任務(wù)。
- 一幀內(nèi) (大多是16ms) ,可執(zhí)行多個(gè)宏任務(wù)以及他們的微任務(wù)。
- 如果宏任務(wù)以及微任務(wù)執(zhí)行時(shí)間過長,那么會(huì)阻塞UI線程的工作,導(dǎo)致頁面卡頓、掉幀。
- 宏任務(wù)產(chǎn)生的微任務(wù)直接插入當(dāng)前宏任務(wù)的微任務(wù)隊(duì)列,這么做是為了保證任務(wù)執(zhí)行的時(shí)效性。
- 宏任務(wù)執(zhí)行過程中產(chǎn)生的宏任務(wù),會(huì)直接放入消息隊(duì)列的尾部,依次執(zhí)行,新任務(wù)的執(zhí)行時(shí)效性也就無法保證。