前置
Node阶段
- timer: 执行 setTimeout 和 setInterval 回调,由poll阶段控制,另外,定时器事件不是准确的,只能是尽快执行
- poll: IO回调阶段,
- 如果poll不为空,遍历回调队列同步执行
- 如果poll为空,先判断有没有setImmediate,有就进入check阶段执行,没有就执行timer,这里会有个超时控制,防止一直等下去
- setImmediate加入check队列执行
宏任务的执行
setTimeout(() => {
console.log('timeout 1');
Promise.resolve().then(() => console.log('promise 1'))
},0)
setTimeout(() => {
console.log('timeout 2');
Promise.resolve().then(() => console.log('promise 2'))
},0)
结果
浏览器 Node
timeout 1 timeout 1
promise 1 timeout 2
timeout 2 promise 1
promise 2 promise 1
Node在执行宏任务时,会把所有可执行的宏任务一次执行完成(目前12版本好像规范了),浏览器总是微任务优先
setImmediate和setTimeout 0
setTimeout(function timeout () {
console.log('timeout');
},0);
setImmediate(function immediate () {
console.log('immediate');
});
结果
浏览器 Node
immediate 顺序不定
timeout
Node的setImmediate是在poll阶段完成check阶段执行的,setTimeout是在pool空闲时执行,因为进入事件循环也需要时间,所以这两个执行顺序不确定,但是如果像下面这样
const fs = require('fs')
fs.readFile(__filename, () => {
setTimeout(() => {
console.log('timeout');
}, 0)
setImmediate(() => {
console.log('immediate')
})
})
setImmediate会先执行,因为事件是IO回调,也就是poll阶段,所以先执行
process.nextTick
process.nextTick是独立于Event Loop,天生比timer和微任务先执行