Node事件环
- 微任务的概念(promise.then process.nextTick)
- timers 时间 setTimeout setInterval
- poll 轮询 i/o回调 fs.readFile()
- check setImmediate方法
默认会从上到下依次执行,如果代码执行到poll后,发现check阶段没有,那就在poll阶段等待(时间到没到)时间到达到清空代码执行。
和浏览器不太一样的是,浏览器是在执行宏任务就把内部的微任务优先执行。
node则是执行只要队列发生切换时就会执行微任务。
setTimeout(()=>{
console.log('timeout')
})
console.log('start');
process.nextTick(()=>{
console.log('nextTick');
});
Promise.resolve().then(data=>{
console.log('then')
})
代码执行顺序为先执行主任务,console.log('start');
然后开始切换时间队列定时器
,只要队列发生切换就会执行微任务。所以会执行nextTick()和Promise的then方法
,再执行定时器中的代码。
看到这里大家就会就觉得和浏览器的事件循环好像一模一样呀。其实不然,有时会有差异。这个千万小心。
setTimeout(()=>{
console.log('timeout1')
process.nextTick(()=>{
console.log('nextTick2');
});
})
console.log('start');
process.nextTick(()=>{
console.log('nextTick1');
setTimeout(()=>{
console.log('timeout2')
})
});
这段代码的执行结果可以是
第一种情况:
start
nextTick1
timeout1
nextTick2
timeout2
第二种情况
start
nextTick1
timeout1
timeout2
nextTick2
这种情况在debug下,我们刻意延迟时间,让代码执行。最终会发现执行结果如下。
setTimeout(()=>{
console.log('timeout1')
process.nextTick(()=>{
console.log('nextTick2');
});
})
console.log('start');
process.nextTick(()=>{
console.log('nextTick1');
setTimeout(()=>{
console.log('timeout2')
})
});
setImmediate(()=>{
console.log('setImmediate');
});
setTimeout(()=>{
console.log('setTimeout');
})
这段代码的执行结果也有很多情况
第一种情况
start
nextTick1
timeout1
nextTick2
setImmediate
setTimeout
timeout2
第二种情况
start
nextTick1
timeout1
setTimeout
nextTick2
setImmediate
timeout2
第三种情况
start
nextTick1
timeout1
setTimeout
timeout2
nextTick2
setImmediate
切换队列的情况: 把队列清空、如果执行大量的回调,超过了最大限制,就会切换队列
经典面试题
const fs = require('fs');
fs.readFile('./package.json','utf-8',()=>{
setTimeout(()=>{
console.log('setTimeout');
});
setImmediate(()=>{
console.log('setImmediate');
});
})
执行结果为setImmediate
setTimeout
。这是因为进入IO
之后随之进入check
阶段,然后才会进入下次事件循环中。
网友评论