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



我有以下用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是否保证两者都将始终运行,或者这只是运气好吗?

在查看.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()

在执行任何侦听器之前,制作侦听器数组的副本。这是意料之中的事,因为如果在迭代时允许代码自由修改正在迭代的数组,那么该数组的迭代可能会被打乱(重复或跳过)。因此,它会在调用任何一个侦听器之前冻结要调用的侦听器集。

相关内容

  • 没有找到相关文章

最新更新