歡迎訪問我的部落格看原文...摸我
學習node eventLoop
的童鞋請注意區分噢....本文程式碼都只在瀏覽器下進行
任務分類
巨集任務(macrotask)
setTimeOut
、setInterval
、setImmediate
、I/O
、 各種callback
、UI渲染等
- 優先順序:
主程式碼塊
>setImmediate
>MessageChannel
>setTimeOut
/setInterval
微任務(microtask)
process.nextTick
、Promise
、MutationObserver
、async(實質上也是promise)
- 優先順序:
process.nextTick
>Promise
>MutationOberser
執行分割槽
我們常常吧EventLoop中分為 記憶體、執行棧、WebApi、非同步回撥佇列(包括微任務佇列和巨集任務佇列)
執行棧
- 執行棧是巨集任務被執行的地方
巨集任務 & 巨集任務佇列
- 巨集任務總會在下一個
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:
過程動畫
答案
1 3 2 5 6 __ 等待一秒___ 7 8 9 4
其他相關
setTimeout
Q: 我的setTimeout
函式到時間了,為啥一直不去執行。
A: setTimeOut
的回撥會被放到任務佇列中,需要當前的執行棧執行完了,才會去執行執行任務佇列中的內容。出現setTimeout
回撥不及時,說明在執行棧中出現了阻塞,或者說執行程式碼過多。
nextTick
常見的vue.$nextTick
會把事件直接插入到當前微任務
佇列的中,感興趣的請看我的筆記《vue_nextTick與eventLoop》 傳送門-->
和 《vue_DOM更新與nextTick》傳送門-->