nodejs中怎么实现事件循环,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
当Node.js启动时会初始化event loop,每个event loop 都会包含按如下六个节点循环,nodejs事件循环和浏览器事件循环完全不一样。

阶段概览
timers(定时器): 此阶段执行那些有setTimeout() 和 setInterval()调度的回调函数;
I/O callbacks(I/O回调):此阶段会执行几乎所有的回调函数,除了close callbacks(关闭回调) 和 那些有timers与setImmediate()调度的回调;
idle(空转),prepare: 此阶段只在内部使用;
poll(轮询): 检索新的I/O事件;在恰当的时候Node会阻塞在这个节点;
check(检查): setImmediate() 设置的回调会在此阶段被调用;
close callbacks(关闭事件的回调):
如果event loop 进入了poll阶段,且代码未设定timer,将会发生下面的情况:
如果event loop进入了poll阶段,且代码设定了timer:
setImmediate约定于setTimeout(cb,0)
var fs = require('fs');
var path = require('path');
function someAsyncOperation(callback) {
// 花费2ms
fs.readFileSync('./read.txt', callback);
}
var timeoutScheduled = Date.now();
var fileReadTime = 0;
setTimeout(function() {
var delay = Date.now() - timeoutScheduled;
console.log(`setTimeout ${delay} ms have passed since I was sheculed`);
console.log('fileReaderTime', fileReadTime - timeoutScheduled);
}, 10);
someAsyncOperation(function() {
fileReadtime = Date.now();
while (Date.now() - fileReadTime < 20) {}
});
执行过程:
setTimeout和readFile先后加入io
setTimeout执行进入io;(需要10ms)
readfile执行,也进入io;(需要2ms)
2ms之后, redfile已经读取完毕,加入poll队列,此时poll为空,执行someAsyncOperation回调;
由于此回调有while,这里阻塞20ms;执行完为22ms
在10ms时,setTimeout不能执行,因为js是单线程,setTimeout一直被阻塞
执行完之后(22ms以后),poll 进入空闲状态
event loop检查timer,setTimeout回调;
执行结果:
readFile执行22ms
setTimeout执行22ms之后
var fs = require('fs');
var path = require('path');
function someAsyncOperation(callback) {
// 花费9ms
fs.readFileSync('./read.txt', callback);
}
var timeoutScheduled = Date.now();
var fileReadTime = 0;
setTimeout(function() {
var delay = Date.now() - timeoutScheduled;
console.log(`setTimeout ${delay} ms have passed since I was sheculed`);
console.log('fileReaderTime', fileReadTime - timeoutScheduled);
}, 5);
someAsyncOperation(function() {
fileReadtime = Date.now();
while (Date.now() - fileReadTime < 20) {}
});
执行结果
setTimeout执行:5ms
readFile执行9 ~ 29ms
在nodejs中,setTimeout(fn,0) === setTimeout(fn,0)
在浏览器中,setTimeout(fn,0) === setTimeout(fn,4)
setImmediate(() =>{
console.log('setImmediate')
},0)
setTimeout(() =>{
console.log('setTimeout')
},0)
// setTimeout 和 setImmediate的执行顺序不确定
// 因为event loop的启动也是需要时间的,可能执行到poll阶段时已经超过了1ms,此时setTimeout会先执行
const fs = require('fs');
const path = require('path');
fs.readFile(path.resolve(__dirname, '/read.txt'), () => {
setTimeout(() => {
console.log('setTimeout');
}, 0);
setImmediate(() => {
console.log('setImmediate');
}, 0);
});
// 执行顺序是确定的, setImmediate,setTimeout
执行过程:
执行fs,第一轮主线程没有timer和setImmediate
假设readFile需要2ms,执行回调
由poll进入check,setImmediate会先调用
在第二轮的timer阶段,会执行setTimeout
关于nodejs中怎么实现事件循环问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注天达云行业资讯频道了解更多相关知识。