Node 事件循环
Node.js 中的事件循环
浏览器和
Node 端,microtask 在事件循环的各个阶段之间执行- 浏览器端,
microtask 在事件循环的macrotask 执行完之后执行
Node.js 事件循环机制
setImmediate 与setTimeout 对比
上文中我们介绍过
//index.js
setTimeout(function(){
console.log("SETTIMEOUT");
});
setImmediate(function(){
console.log("SETIMMEDIATE");
});
//run it
node index.js
上述代码的执行结果并不固定,在介绍
┌───────────────────────┐
┌─>│timers │
│└──────────┬────────────┘
│┌──────────┴────────────┐
││ IO callbacks │
│└──────────┬────────────┘
│┌──────────┴────────────┐
││ idle, prepare │
│└──────────┬────────────┘┌───────────────┐
│┌──────────┴────────────┐│ incoming: │
││ poll│<─────┤connections, │
│└──────────┬────────────┘│ data, etc.│
│┌──────────┴────────────┐└───────────────┘
││check│
│└──────────┬────────────┘
│┌──────────┴────────────┐
└──┤close callbacks│
└───────────────────────┘
//index.js
var fs = require('fs');
fs.readFile("my-file-path.txt", function() {
setTimeout(function(){
console.log("SETTIMEOUT");
});
setImmediate(function(){
console.log("SETIMMEDIATE");
});
});
//run it
node index.js
//output (always)
SETIMMEDIATE
SETTIMEOUT
var Suite = require('benchmark').Suite
var fs = require('fs')
var suite = new Suite
suite.add('deffered.resolve()', function(deferred) {
deferred.resolve()
}, {defer: true})
suite.add('setImmediate()', function(deferred) {
setImmediate(function() {
deferred.resolve()
})
}, {defer: true})
suite.add('setTimeout(,0)', function(deferred) {
setTimeout(function() {
deferred.resolve()
},0)
}, {defer: true})
suite
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})
// 输出
deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)
浏览器中实现setImmediate
当我们使用
Node.js Event Loop

┌───────────────────────┐
┌─>│timers │
│└──────────┬────────────┘
│┌──────────┴────────────┐
││ IO callbacks │
│└──────────┬────────────┘
│┌──────────┴────────────┐
││ idle, prepare │
│└──────────┬────────────┘┌───────────────┐
│┌──────────┴────────────┐│ incoming: │
││ poll│<─────┤connections, │
│└──────────┬────────────┘│ data, etc.│
│┌──────────┴────────────┐└───────────────┘
││check│
│└──────────┬────────────┘
│┌──────────┴────────────┐
└──┤close callbacks│
└───────────────────────┘
nextTick 与setImmediate
我们通过比较以下两个用例来了解
- setImmediate
setImmediate(function A() {
setImmediate(function B() {
log(1);
setImmediate(function D() { log(2); });
setImmediate(function E() { log(3); });
});
setImmediate(function C() {
log(4);
setImmediate(function F() { log(5); });
setImmediate(function G() { log(6); });
});
});
setTimeout(function timeout() {
console.log('TIMEOUT FIRED');
}, 0)
// 'TIMEOUT FIRED' 1 4 2 3 5 6
// OR
// 1 'TIMEOUT FIRED' 4 2 3 5 6
- nextTick
process.nextTick(function A() {
process.nextTick(function B() {
log(1);
process.nextTick(function D() {
log(2);
});
process.nextTick(function E() {
log(3);
});
});
process.nextTick(function C() {
log(4);
process.nextTick(function F() {
log(5);
});
process.nextTick(function G() {
log(6);
});
});
});
setTimeout(function timeout() {
console.log("TIMEOUT FIRED");
}, 0);
// 1 4 2 3 5 6 'TIMEOUT FIRED'
如上文所述,通过