删除当前正在发出的事件的事件侦听器

我有以下示例应用程序,用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检查了这个)

我的问题的背景是:如果我绑定两个事件处理程序到一个stream的end事件,其中一个调用removeAllListeners ,Node.js是否保证两个将始终运行,或者这只是一个好运?

在查看.emit()方法的实现时,它看起来像一旦它开始处理一个事件并调用监听器,那么这个事件将不会被任何调用removeAllListeners()代码影响,所以在你的例子中,这两个监听器都将被调用。

.emit()的代码在执行任何一个侦听器之前创build一个侦听器数组的副本,以便一旦它开始执行,它将执行所有这些侦听器,即使它们在执行期间被移除。 这是相关的一段代码:

  } 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() 

在执行任何侦听器之前创build侦听器数组的副本。 这是可以预料的,因为如果代码被自由地允许修改正在被迭代的被迭代的数组,那么该数组的迭代可能会被搞乱(重复或跳过)。 所以,在调用任何一个监听器之前,它将冻结一组监听器。