Node.js EventEmitter: how to associate a class context with an event listener, and then remove this listener

Is there a way to access the class context in the event listener method with the ability to remove the listener?

Example 1:

import {EventEmitter} from "events"; export default class EventsExample1 { private emitter: EventEmitter; constructor(private text: string) { this.emitter = new EventEmitter(); this.emitter.addListener("test", this.handleTestEvent); this.emitter.emit("test"); } public dispose() { this.emitter.removeListener("test", this.handleTestEvent); } private handleTestEvent() { console.log(this.text); } } 

In this example, removing the listener works, but the handleTestEvent() method does not have access to the class context using this . this points to an EventEmitter context, so this.text not available.

Example 2:

 import {EventEmitter} from "events"; export default class EventsExample2 { private emitter: EventEmitter; constructor(private text: string) { this.emitter = new EventEmitter(); this.emitter.addListener("test", this.handleTestEvent.bind(this)); this.emitter.emit("test"); } public dispose() { this.emitter.removeListener("test", this.handleTestEvent); } private handleTestEvent() { console.log(this.text); } } 

In this example, I use the bind function to bind the class context to an event listener. Now the handleTestEvent method has access to the class context using this => this.text , but the listener cannot be removed using removeListener - it seems that bind creates a new anonymous function, so there is no link to the limited listener.

Example 3:

 import {EventEmitter} from "events"; export default class EventsExample3 { private emitter: EventEmitter; constructor(private text: string) { this.emitter = new EventEmitter(); this.emitter.addListener("test", () => this.handleTestEvent()); this.emitter.emit("test"); } public dispose() { this.emitter.removeListener("test", this.handleTestEvent); } private handleTestEvent() { console.log(this.text); } } 

In this example, I use the arrow function to save the context of the class in an event listener. handleTestEvent has access to the class context using this , but the listener cannot be deleted (there is no reference to the restricted listener, as in example 2).

I tried an alternative event library - EventEmitter3 , which supports a custom context for events (the class context can be passed as the third parameter to the addListener function ( this.emitter.addListener("test", this.handleTestEvent, this ), it works fine, but I prefer to use included EventEmitter from Node.js.

+6
source share
2 answers

You can do this in the constructor:

 this.handleTestEvent = this.handleTestEvent.bind(this); this.emitter.addListener("test", this.handleTestEvent); 

If you want to use the leading edge, you can use the proposed snap operator as a shortcut:

 this.handleTestEvent = ::this.handleTestEvent; this.emitter.addListener("test", this.handleTestEvent); 

Or use the property initializer to create a related method:

 constructor(private text: string) { this.emitter = new EventEmitter(); this.emitter.addListener("test", this.handleTestEvent); this.emitter.emit("test"); } handleTestEvent = () => { console.log(this.text); } 
+4
source

You probably sorted it, but you could just do

 import {EventEmitter} from "events"; class HasEvents extends EventEmitter {} const emitter = new HasEvents(); 
0
source

All Articles