我有以下示例应用程序,用 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
不会影响当前绑定(bind)到该事件的事件监听器。这是随机的,还是故意的? (我使用 0.10.32 和 0.11.13 检查了这一点)
我的问题的背景是:如果我将两个事件处理程序绑定(bind)到流的 end
事件,并且其中一个调用 removeAllListeners
,Node.js 是否能保证两者总是会被运行,还是这只是运气好?
最佳答案
在查看 .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()
在执行任何监听器之前创建监听器数组的副本。这是可以预料的,因为如果允许代码在迭代时自由修改正在迭代的数组,则该数组的迭代可能会困惑(重复或跳过)。因此,它会在调用任何监听器之前卡住要调用的监听器集。
关于node.js - 删除当前发出事件的事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26634943/