│ ┌───────────┴───────────┐ └──────────────┘
╰───┤ setImmediate │
└───────────────────────┘
关于事件循环的内部运行机制,有一些理解困难的地方:
所有回调都会经由process.nextTick(),在事件循环(例如,定时器)一个阶段的结束并转换到下一阶段之前预设定。这就会避免潜在的递归调用process.nextTick(),而造成的无限循环。
“Pending callbacks(待回调)”,是回调队列中不会被任何其他事件循环周期处理(例如,传递给fs.write)的回调。
Event Emitter 和 Event Loop
通过创建EventEmitter,可简化与事件循环的交互。它是一个通用的封装,可以让你更容易地创建基于事件的API。关于这两者如何互动往往让开发者感到混乱。
下面的例子表明,忘记了事件是同步触发的,可能导致事件被错过。
// v0.10以后,不再需要require(‘events’).EventEmitter
var EventEmitter = require(‘events’);
var util = require(‘util’);
function MyThing() {
EventEmitter.call(this);
doFirstThing();
this.emit(‘thing1’);
}
util.inherits(MyThing, EventEmitter);
var mt = new MyThing();
mt.on(‘thing1’, function onThing1() {
// 抱歉,这个事件永远不会发生
});
上面的’thing1’事件,永远不会被MyThing()捕获,因为MyThing()必须在实例化后才能侦听事件。下面的是一个简单的解决方法,不必添加任何额外的闭包:
var EventEmitter = require(‘events’);
var util = require(‘util’);
function MyThing() {
EventEmitter.call(this);
doFirstThing();
setImmediate(emitThing1, this);
}
util.inherits(MyThing, EventEmitter);
function emitThing1(self) {
self.emit(‘thing1’);
}
var mt = new MyThing();
mt.on(‘thing1’, function onThing1() {
// 执行了
});
下面的方案也可以工作,不过要损失一些性能:
function MyThing() {
EventEmitter.call(this);
doFirstThing();
// 使用 Function#bind() 会损失性能
setImmediate(this.emit.bind(this, ‘thing1’));
}
util.inherits(MyThing, EventEmitter);









