我有以下示例应用程序,用Node.js编写:
'use strict';
var events = require('events'),
util = require('util');
var EventEmitter = events.EventEmitter;
var Foo = function () {};
util.inherits(Foo, EventEmitter);
var foo = new Foo();
foo.once('x', function () {
foo.removeAllListeners();
console.log('Google!');
});
foo.once('x', function () {
foo.removeAllListeners();
console.log('Yahoo!');
});
foo.emit('x');
打印:
Google!
Yahoo!
现在我的问题是:显然removeAllListeners
不会影响当前绑定到事件的事件侦听器。这是随机的,还是意图? (我用0.10.32以及0.11.13检查了这个)
我的问题的背景是:如果我将两个事件处理程序绑定到流的end
事件,其中一个调用removeAllListeners
,Node.js是否保证两者都将始终跑步,还是只是祝你好运?
答案 0 :(得分:2)
在查看.emit()
方法的实现时,看起来一旦它开始处理事件并调用侦听器,该事件就不会受到调用removeAllListeners()
的任何代码的影响,所以在您的示例中两个听众都会被召唤。
.emit()
的代码在执行任何侦听器之前复制了侦听器数组,这样一旦它开始执行一个侦听器,它就会执行所有侦听器,即使它们在执行期间被删除。这是相关的代码:
} else if (util.isObject(handler)) {
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
从这里的EventEmitter实现:https://github.com/joyent/node/blob/857975d5e7e0d7bf38577db0478d9e5ede79922e/lib/events.js#L120
在这段代码中,handler
将是一个监听器函数数组。这条线
listeners = handler.slice()
在执行任何侦听器之前复制侦听器数组。这是可以预料到的,因为如果代码可以自由地允许修改正在迭代的迭代数组,那么该数组的迭代可能会混乱(重复或跳过)。因此,它会在调用任何侦听器之前冻结要调用的侦听器集。