整個js這種運行機制又稱爲Event Loop(事件循環)node
上代碼感覺一下瀏覽器
setTimeout(() => {
console.log(1)
Promise.resolve(3).then(data => console.log(data))
}, 0)
setTimeout(() => {
console.log(2)
}, 0)
//瀏覽器 1 3 2
//node 1 2 3
複製代碼
首先就是執行時會有一個棧 而後有一個事件隊列和微任務空間(本身命名的)bash
當咱們的代碼從上到下同步執行時,遇到setTimeout就記時,當時間到時就把此事件放到事件隊列中,遇到微任務就把微任務放到微任務空間,代碼會繼續向下執行,直到同步代碼執行完畢。異步
完畢後,會看看微任務空間中有沒有微任務,有就把微任務空間中的微任務所有執行,而後去隊列中取咱們的事件執行,執行時如有微任務繼續放到微任務空間,當此事件執行完畢,還會把微任務空間中的微任務所有執行完畢,而後再去取隊列中的異步任務。。。。反覆循環oop
有圖有真相(是否是很醜!醜也別說出來)ui
想上個醜圖spa
setImmediate 設計在poll階段完成時執行,即check階段; setTimeout 設計在poll階段爲空閒時,且設定時間到達後執行;但其在timer階段執行 其兩者的調用順序取決於當前event loop的上下文,若是他們在異步i/o callback以外調用(在i/o內調用由於下一階段爲check階段),其執行前後順序是不肯定的,須要看loop的執行前的耗時狀況設計
廢話很少說,上代碼code
setImmediate(() => {
console.log('setImmediate1')
setTimeout(() => {
console.log('setTimeout1')
}, 0);
})
setTimeout(()=>{
console.log('setTimeout2')
setImmediate(()=>{
console.log('setImmediate2')
})
},0);
//首先setImmediate和setTimeout執行順序不固定
//因此setImmediate1和setTimeout2,打印順序不定
//假設 setImmediate1先打印 有兩種順序
//1.執行順序是 setImmediate1 setTimeout2 setTimeout1 setImmediate2
//2.執行順序是 setImmediate1 setTimeout2 setImmediate2 setTimeout1
// 1.setImmediate1打印後把setTimeout1放進timer隊列 而後執行setTimeout2 這時候把setImmediate2放進check隊列中 打印setTimeout2 發現timer中還有setTimeout1 他就會把timer對列中的執行完 纔會執行下一隊列的代碼
//而後打印setTimeout1, 切換對列到check 打印setImmediate2
//2. setImmediate1打印後把setTimeout1放進timer隊列 而後執行setTimeout2 這時候把setImmediate2放進check隊列中 打印setTimeout2 這個時候node執行過快setTimeout1尚未到時間,因此切換對列執行setImmediate2 而後是setTimeout1
//setTimeout第二個參數雖然是0,可是都有默認時間通常是4ms左右
複製代碼
再來一題cdn
setImmediate(() => {
console.log('setImmediate1')
setTimeout(() => {
console.log('setTimeout1')
}, 0);
})
setTimeout(()=>{
console.log('setTimeout2')
process.nextTick(()=>console.log('nextTick'))
setImmediate(()=>{
console.log('setImmediate2')
})
},0);
//假設setImmediate1先
//setImmediate1 setTimeout2 setTimeout1 nextTick setImmediate2
//setImmediate1 setTimeout2 nextTick setImmediate2 setTimeout1
//微任務會在切換對列時執行 上面從timer對列切換到check對列時nextTick執行
//上面一題明白了這一個也明白了
複製代碼
再來一題
let fs = require('fs');
fs.readFile('./1.txt',function () {
console.log(1);
setTimeout(() => {
console.log('setTimeout')
}, 0);
setImmediate(() => {
console.log('setImmediate')
});
});
//順序固定 1 setImmediate setTimeout
// 爲何呢?看上面的圖 首先readFile確定是poll對列 執行時把setTimeout setImmediate放到各自隊列 而後按上下順序查找對列 查找到check隊列發現有 就把setImmediate打印出 而後順序檢查下一隊列close沒有 循環 再次從上往下找 直到timer打印setTimeout
複製代碼
以上內容是本人試出來的 mac vscode
Promise.resolve('123').then(res=>{
console.log(res);
})
process.nextTick(() => console.log('nextTick'))
//順序 nextTick 123
//很明顯 nextTick快
複製代碼