JS 主線程不斷的循環(huán)往復(fù)的從任務(wù)隊(duì)列中讀取任務(wù)虑啤,執(zhí)行任務(wù)立美,這種運(yùn)行機(jī)制稱為事件循環(huán)(event loop)推薦看一個(gè)2分鐘了解event loop
宏任務(wù)和微任務(wù)
瀏覽器的事件循環(huán)(event loop)中分成宏任務(wù)和微任務(wù)。JS 中任務(wù)分成同步任務(wù)和異步任務(wù)。
- 宏任務(wù)(macro task)
JS 中主棧執(zhí)行的大多數(shù)的任務(wù),例如:定時(shí)器,事件綁定嵌赠,ajax,回調(diào)函數(shù)熄赡,node中fs操作模塊等就是宏任務(wù)
- 微任務(wù)(micro task)
promise, async/await, process.nextTick等就是微任務(wù)姜挺。
為什么要引入微任務(wù),只有宏任務(wù)可以嗎彼硫?
微任務(wù)的引入是為了解決異步回調(diào)的問題炊豪,假設(shè)只有宏任務(wù),那么每一個(gè)宏任務(wù)執(zhí)行完后回調(diào)函數(shù)也放入宏任務(wù)隊(duì)列拧篮,這樣會(huì)造成隊(duì)列多長词渤,回調(diào)的時(shí)間變長,這樣會(huì)造成頁面的卡頓串绩,所以引入了微任務(wù)缺虐。
- 宏任務(wù)和微任務(wù)的執(zhí)行順序(很重要)
- 主棧隊(duì)列就是一個(gè)宏任務(wù),每一個(gè)宏任務(wù)執(zhí)行完就會(huì)執(zhí)行宏任務(wù)中的微任務(wù)礁凡,直到微任務(wù)全部都執(zhí)行完高氮,才開始執(zhí)行下一個(gè)宏任務(wù)。
- js 中任務(wù)的執(zhí)行順序優(yōu)先級(jí)是:主棧全局任務(wù)(宏任務(wù)) > 宏任務(wù)中的微任務(wù) > 下一個(gè)宏任務(wù)顷牌。剪芍,所以 promise(微任務(wù)) 的執(zhí)行順序優(yōu)先級(jí)高于setTimeout定時(shí)器。
- 不能滿目的將 .then 的回調(diào)放入微任務(wù)隊(duì)列窟蓝;因?yàn)闆]有調(diào)用 resolve或者reject 之前是不算異步任務(wù)完成的罪裹, 所以不能將回調(diào)隨意的放入微任務(wù)事件隊(duì)列
- await 是一個(gè)讓出線程的標(biāo)志。await 后面的表達(dá)式會(huì)先執(zhí)行一遍运挫,將 await 后面的代碼加入到 micro task中這個(gè)微任務(wù)是 promise 隊(duì)列中微任務(wù)状共,然后就會(huì)跳出整個(gè) async 函數(shù)來繼續(xù)執(zhí)行后面的代碼。
- process.nextTick 是一個(gè)獨(dú)立于 eventLoop 的任務(wù)隊(duì)列滑臊,主棧中的宏任務(wù)每一次結(jié)束后都是先執(zhí)行 process.nextTick隊(duì)列口芍,在執(zhí)行微任務(wù) promise 的 .then()箍铲。
- 每一個(gè)宏任務(wù)和宏任務(wù)的微任務(wù)執(zhí)行完后都會(huì)對(duì)頁面 UI 進(jìn)行渲染雇卷。