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

时间:2022-03-22 00:02:17

I have the following sample app, written in Node.js:

我有以下示例应用程序,用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');

It prints:

Google!
Yahoo!

Now my question is: Apparently the removeAllListeners does not affect the event listeners that are currently bound to the event. Is this by random, or is this by intent? (I checked this out using 0.10.32 as well as 0.11.13)

现在我的问题是:显然removeAllListeners不会影响当前绑定到事件的事件侦听器。这是随机的,还是意图? (我用0.10.32和0.11.13检查了这个)

The background of my question is: If I bind two event handlers to a stream's end event, and one of them calls removeAllListeners, does Node.js guarantee that both will always be run, or is this just by good luck?

我的问题的背景是:如果我将两个事件处理程序绑定到一个流的结束事件,并且其中一个调用removeAllListeners,那么Node.js是否保证两者都将一直运行,或者这只是好运?

1 个解决方案

#1


2  

In looking at the implementation of the .emit() method, it looks like once it starts processing an event and calling listeners, that event will not be affected by any code that calls removeAllListeners() so in your example both listeners will be called.

在查看.emit()方法的实现时,看起来一旦它开始处理事件并调用侦听器,该事件就不会受到调用removeAllListeners()的任何代码的影响,因此在您的示例中将调用两个侦听器。

The code for .emit() makes a copy of the array of listeners before executing any of them so that once it starts executing one, it will execute all of them, even if they are removed during execution. Here's the relevant piece of code:

.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);
  }

From the EventEmitter implementation here: https://github.com/joyent/node/blob/857975d5e7e0d7bf38577db0478d9e5ede79922e/lib/events.js#L120

从这里的EventEmitter实现:https://github.com/joyent/node/blob/857975d5e7e0d7bf38577db0478d9e5ede79922e/lib/events.js#L120

In this piece of code, handler will be an array of listener functions. The line

在这段代码中,handler将是一个监听器函数数组。这条线

listeners = handler.slice()

makes a copy of the listeners array before any listeners are executed. This is to be expected because iteration of that array can be messed up (duplicates or skips) if code is freely allowed to modify the array being iterated while it is being iterated. So, it freezes the set of listeners to be called before calling any of them.

在执行任何侦听器之前创建侦听器数组的副本。这是可以预料到的,因为如果可以*地允许代码在迭代时修改正在迭代的数组,那么该数组的迭代可能会混乱(重复或跳过)。因此,它会在调用任何侦听器之前冻结要调用的侦听器集。

#1


2  

In looking at the implementation of the .emit() method, it looks like once it starts processing an event and calling listeners, that event will not be affected by any code that calls removeAllListeners() so in your example both listeners will be called.

在查看.emit()方法的实现时,看起来一旦它开始处理事件并调用侦听器,该事件就不会受到调用removeAllListeners()的任何代码的影响,因此在您的示例中将调用两个侦听器。

The code for .emit() makes a copy of the array of listeners before executing any of them so that once it starts executing one, it will execute all of them, even if they are removed during execution. Here's the relevant piece of code:

.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);
  }

From the EventEmitter implementation here: https://github.com/joyent/node/blob/857975d5e7e0d7bf38577db0478d9e5ede79922e/lib/events.js#L120

从这里的EventEmitter实现:https://github.com/joyent/node/blob/857975d5e7e0d7bf38577db0478d9e5ede79922e/lib/events.js#L120

In this piece of code, handler will be an array of listener functions. The line

在这段代码中,handler将是一个监听器函数数组。这条线

listeners = handler.slice()

makes a copy of the listeners array before any listeners are executed. This is to be expected because iteration of that array can be messed up (duplicates or skips) if code is freely allowed to modify the array being iterated while it is being iterated. So, it freezes the set of listeners to be called before calling any of them.

在执行任何侦听器之前创建侦听器数组的副本。这是可以预料到的,因为如果可以*地允许代码在迭代时修改正在迭代的数组,那么该数组的迭代可能会混乱(重复或跳过)。因此,它会在调用任何侦听器之前冻结要调用的侦听器集。