瀏覽器 Javascript 的 EventLoop 動態圖析

HXWfromDJTU發表於2018-09-11

歡迎訪問我的部落格看原文...摸我
學習node eventLoop的童鞋請注意區分噢....本文程式碼都只在瀏覽器下進行


任務分類

巨集任務(macrotask)

  • setTimeOutsetIntervalsetImmediateI/O 、 各種callbackUI渲染等
  • 優先順序: 主程式碼塊 > setImmediate > MessageChannel > setTimeOut/setInterval

微任務(microtask)

  • process.nextTickPromiseMutationObserverasync(實質上也是promise)
  • 優先順序: process.nextTick > Promise > MutationOberser

執行分割槽

我們常常吧EventLoop中分為 記憶體、執行棧、WebApi、非同步回撥佇列(包括微任務佇列和巨集任務佇列)

瀏覽器 Javascript 的 EventLoop 動態圖析

執行棧

  • 執行棧是巨集任務被執行的地方

巨集任務 & 巨集任務佇列

  • 巨集任務總會在下一個EventLoop中執行
  • 若在執行巨集任務的過程中,加入了新的微任務,會把新的微任務新增到微任務的佇列中。

微任務 & 微任務佇列

  • 若在執行微任務的過程中,加入了新的微任務,會把新的微任務新增在當前任務佇列的隊尾巴。
  • 微任務會在本輪EventLoop執行完後,馬上把執行棧中的任務都執行完畢。

執行流程

Javascript核心載入程式碼到執行棧
執行棧依次執行主執行緒的同步任務,過程中若遇呼叫了非同步Api則會新增回撥事件到回撥佇列中。且微任務事件新增到微任務佇列中,巨集任務事件新增到巨集任務佇列中去。直到當前執行棧中程式碼執行完畢。
③ 開始執行當前所有微任務佇列中的微任務回撥事件。 (:smirk:注意是所有哦,相當於清空佇列)
④ 取出巨集任務佇列中的第一條(先進先出原則哦)巨集任務,放到執行棧中執行。
⑤ 執行當前執行棧中的巨集任務,若此過程總又再遇到微任務或者巨集任務,繼續把微任務巨集任務進行各自隊伍的入隊操作,然後本輪的巨集任務執行完後,又把本輪產生的微任務一次性出隊都執行了。
⑥ 以上操作往復迴圈...就是我們平時說的eventLoop

....特點是

  • 微任務佇列操作,總是會一次性清空佇列
  • 巨集任務佇列每次只會取出一條任務到執行棧中執行

輔助理解

let promiseGlobal = new Promise(resolve=>{
  console.log(1)
  resolve('2')
})
console.log(3) 

promiseGlobal.then(data=>{
  console.log(data)
  let setTimeoutInner = setTimeout(_=>{
  console.log(4)
   },1000)
   let promiseInner =new Promise(resolve=>{
     console.log(5) 
      resolve(6)
    }).then(data=>{
     console.log(data)
   })
})
let setTimeoutGlobal = setTimeout(_=>{
  console.log(7);
 let promiseInGlobalTimeout = new Promise(resolve=>{
      console.log(8); 
      resolve(9)
  }).then(data=>{
     console.log(data)
  })
},1000) 
複製程式碼

建議不要直接拷貝到 控制檯跑...大家先想想:smirk:

過程動畫

瀏覽器 Javascript 的 EventLoop 動態圖析
瀏覽器 Javascript 的 EventLoop 動態圖析

答案

1 3 2 5 6 __ 等待一秒___ 7 8 9 4


其他相關

setTimeout

Q: 我的setTimeout函式到時間了,為啥一直不去執行。

A: setTimeOut的回撥會被放到任務佇列中,需要當前的執行棧執行完了,才會去執行執行任務佇列中的內容。出現setTimeout回撥不及時,說明在執行棧中出現了阻塞,或者說執行程式碼過多。

nextTick

常見的vue.$nextTick會把事件直接插入到當前微任務佇列的中,感興趣的請看我的筆記《vue_nextTick與eventLoop》 傳送門--> 和 《vue_DOM更新與nextTick》傳送門-->


其他文章

歡迎star我的github

async/await 實現非同步程式設計

你瞭解GET和POST嗎

veu_nextTick與eventLoop

相關文章