Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

eventEmitter.removeListener calls removed listener within emit cycle #7872

Closed
RGBboy opened this issue Jul 1, 2014 · 7 comments
Closed

eventEmitter.removeListener calls removed listener within emit cycle #7872

RGBboy opened this issue Jul 1, 2014 · 7 comments

Comments

@RGBboy
Copy link

RGBboy commented Jul 1, 2014

I am trying to remove an event listener during the emit cycle of an event. I would have thought the following code would not fail. Am I right in this assumption or should all of these event listeners be called?

  var emitter = new EventEmitter();

  t.plan(2);

  function one () {
    t.ok('called');
    emitter.removeListener('test', two);
  };

  function two () {
    t.fail('should not be called');
  };

  function three () {
    t.ok('called');
  };

  emitter.on('test', one);
  emitter.on('test', two);
  emitter.on('test', three);

  emitter.emit('test');
@RGBboy RGBboy changed the title eventEmitter.removeListener calls removed listener within eventEmitter.removeListener calls removed listener within emit cycle Jul 1, 2014
@jfhbrook
Copy link

jfhbrook commented Jul 1, 2014

Two should fire exactly once.

@jfhbrook
Copy link

jfhbrook commented Jul 1, 2014

If this was buggy, it would fire twice.

@RGBboy
Copy link
Author

RGBboy commented Jul 1, 2014

OK thanks. Is there a way to prevent listeners from being called if they are removed during the emit cycle?

@jfhbrook
Copy link

jfhbrook commented Jul 1, 2014

Don't create them during the emit cycle. ;) Do it on the next tick or similar.

@indutny
Copy link
Member

indutny commented Jul 1, 2014

This is an intended behavior, sorry. Please continue the discussion on a mailing list.

@kenzanboo
Copy link

@indutny
The node documentation for emit says that emit will "Execute each of the listeners in order ... " so if the first listener removes the second listener, it would be expected that the second listener does not get executed. In the above example, because listener one removes the listener two, and it is executed first, two should not have executed.
None of the removeListener code is deferred so it should update this._event immediately.

@lxe
Copy link

lxe commented Dec 17, 2014

The event API (whose interface is frozen) doc specify:

emitter.emit(event, [arg1], [arg2], [...])
Execute each of the listeners in order with the supplied arguments.

The emitters must be executed in order with which they were attached.

Furthermore, there is nothing in lib/events.js that defers the execution of removeListener.
I think this still should be addressed, or at the least, the docs need to be changed to reflect this behavior.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants