EventLoop,消息隊列,宏任務(wù)與微任務(wù)

一、js為什么是單線程?

js是單線程語言,因為它的主要用途是與用戶交互及操作dom,如果多線程的話,一個線程在一個dom節(jié)點添加內(nèi)容,另一個線程刪除了這個節(jié)點,瀏覽器不知道以哪個線程為準。js單線程是指瀏覽器中負責解釋和執(zhí)行js代碼的只有一個線程->js引擎線程。瀏覽器是多線程的有:js引擎線程、事件觸發(fā)線程、定時觸發(fā)

二、EventLoop

js單線程意味著js會按照事件順序執(zhí)行,若其中某一個事件耗時很久,后面的事件會阻塞,但是我們發(fā)現(xiàn)js中定時器,異步請求并不會阻塞后續(xù)事件執(zhí)行,這是為什么呢?

其實,當有計時器、網(wǎng)絡(luò)請求等異步事件時,js會把它們放到WebAPI中,WebAPI是瀏覽器提供的線程,然后js會執(zhí)行后面的其他事件,WebAPI中的異步事件結(jié)束后,會把事件的回調(diào)函數(shù)放到任務(wù)隊列中去維護,js會在適當?shù)臅r間去任務(wù)隊列取出回調(diào)函數(shù)執(zhí)行

消息隊列類似隊列的數(shù)據(jù)結(jié)構(gòu),遵循先入先出規(guī)則,用于存儲消息

JS有執(zhí)行棧和任務(wù)隊列,同步任務(wù)依次進入執(zhí)行棧,異步任務(wù)會放入任務(wù)隊列,執(zhí)行棧中任務(wù)結(jié)束后會讀取任務(wù)隊列,對應(yīng)的異步任務(wù)結(jié)束等待狀態(tài)進入執(zhí)行棧開始執(zhí)行;這個運行機制就是事件循環(huán),自己理解的運行流程圖如下:

js執(zhí)行流程.png

三、宏任務(wù)與微任務(wù)

宏任務(wù)和微任務(wù)是異步編程的兩種任務(wù)

宏任務(wù)包括:script(外層同步代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering;

微任務(wù)包括: Promises, Object.observe, MutationObserver

涉及到此就不得不提經(jīng)常面試問到的宏任務(wù)與微任務(wù)的執(zhí)行順序

一輪事件循環(huán)首先執(zhí)行宏任務(wù)=>執(zhí)行所有微任務(wù)=>UI render=>下一輪事件循環(huán)


宏任務(wù)與微任務(wù)執(zhí)行順序.png
console.log(1)
setTimeout(function timer1 () { 
  console.log(2)
}, 1800)
new Promise((resolve, reject)=>{
  console.log(3)
  resolve(123)
}).then(res=>{
  console.log(4)
})
console.log(5)
//打印結(jié)果:1 3 5 4 2
//整個代碼片段是一個宏任務(wù),setTimeout是一個新的宏任務(wù),要等到本輪微任務(wù)結(jié)束才開啟




console.log(1)
setTimeout(function timer1 () { 
  console.log(2)
}, 1800)
new Promise((resolve, reject)=>{
  console.log(3)
  setTimeout(function timer1 () { 
    console.log(4)
    resolve(123)
  }, 1800)
}).then(res=>{
  console.log(5)
})
console.log(6)
// 打印結(jié)果:1 3 6 2 4 5
// Promise中的setTimeout會放到WebAPI中,因為第一個setTimeout先放進去的定時也是1800,所以第一個先執(zhí)行打印2

console.log(1)
setTimeout(function timer1 () { 
  console.log(2)
}, 1800)
new Promise((resolve, reject)=>{
  console.log(3)
  setTimeout(function timer1 () { 
    console.log(4)
    resolve(123)
  }, 1700)
}).then(res=>{
  console.log(5)
})
console.log(6)
// 打印結(jié)果:1 3 6 4 5 2
// Promise中的setTimeout會放到WebAPI中,因為第一個setTimeout先放進去的定時比第二個時間長,所以先走第二個,接著會把對應(yīng)的微任務(wù)走完,接著才會走剩下的setTimeout中任務(wù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容