eventemitter3 icon indicating copy to clipboard operation
eventemitter3 copied to clipboard

[api] Add removeListenersByContext(context) method

Open onlywei opened this issue 6 years ago • 8 comments

I find it very convenient when cleaning up my EventEmitters to remove all listeners that were added with a specific context. This allows me to avoid having to save bound references to my callback functions for use later in my destroy lifecycle methods.

onlywei avatar Jul 26 '18 20:07 onlywei

Hmm, not really sure what this username and accessKey stuff for SAUCE is all about. Unit tests pass for sure.

onlywei avatar Jul 26 '18 20:07 onlywei

Encrypted variables are not available to untrusted builds such as pull requests coming from another repository so don't worry about that.

Can we find a better name? Like, I don't know, removeListenersByContext(ctx) or simply removeListeners(ctx), other suggestions are welcome but I think removeContext(ctx) is not a good name.

lpinca avatar Jul 28 '18 05:07 lpinca

@lpinca Thanks. Method renamed.

onlywei avatar Jul 29 '18 00:07 onlywei

@onlywei can't this be done with something like this?

for (const event of ee.eventNames()) {
  for (const listener of ee.listeners(event)) {
    ee.removeListener(event, listener, context);
  }
}

I understand it is inefficient but I wonder if the suggested API will ever be used in hot paths. I'm a bit reluctant about adding this method because:

  • The feature it adds can be easily obtained with the already existing methods.
  • It is another divergence from the Node.js EventEmitter.
  • It increases the size of the library.

lpinca avatar Jul 29 '18 14:07 lpinca

When using EventEmitter with any sort of browser-side framework such as Angular or React, a common pattern is such:

export default class MyReactComponent {
  componentDidMount() {
    // someEE is passed in as a prop here
    this.props.someEE.on('someEvent', () => doSomething(), this);
    // ... attach more listeners ...
  }

  componentWillUnmount() {
    this.props.someEE.removeListenersByContext(this);
  }
}

Angular components have a similar lifecycle using with $onInit and $onDestroy methods.

If we are not destroying our components very often, then I guess this would not be a hot path.

However, imagine that you have a list of components that is paginated and maybe can display hundreds of items per page. In this scenario, every time you paginate or sort or filter, these hundreds of items will destroy themselves and then get re-created.

Is that "hot" enough for this library? I believe only you can decide :) Please let me know your decision. I will adjust my coding in each of my components based on your decision.

onlywei avatar Jul 30 '18 17:07 onlywei

It would be nice to see a benchmark. cc: @3rd-Eden

lpinca avatar Jul 30 '18 17:07 lpinca

I'm indifferent about this addition. I think that most people are now using fat arrows to have the correct context by default so I don't consider this feature that heavily used anymore.

3rd-Eden avatar Jul 31 '18 17:07 3rd-Eden

@3rd-Eden Using fat arrow functions only solves the addEventListener part, but it does not solve the removeListener part of a component's lifecycle since the lifecycle functions are different methods.

onlywei avatar Jul 31 '18 18:07 onlywei