Node.js EventEmitter: How to bind a class context to the event listener and then remove this listener

10,934

You could do this in the constructor:

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

If you want to use cutting edge, you can use the proposed bind operator as a shortcut:

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

Or use a property initializer to create a bound method:

constructor(private text: string) {
  this.emitter = new EventEmitter();

  this.emitter.addListener("test", this.handleTestEvent);
  this.emitter.emit("test");
}

handleTestEvent = () => {
  console.log(this.text);
}
Share:
10,934

Related videos on Youtube

Dominik Palo
Author by

Dominik Palo

My interests: Programming (especially mobile apps, Xamarin, .NET C#, WPF and Node.js), 3D printing (RepRap) and open-hardware

Updated on June 13, 2022

Comments

  • Dominik Palo
    Dominik Palo about 2 years

    Is there a way to access to the class context in the event listener method with possibility 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 has no access to the class context using this. this points to EventEmitter context, so this.text is not accessible.

    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'm using the bind function to bind a context of the class to the event listener. Now handleTestEvent method has access to the class context using this => this.text is accessible, but listener cannot be removed with removeListener - it seems that bind creates a new anonymous function, so there is no reference to the bounded 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'm using an arrow function to preserve a context of the class in the event listener. handleTestEvent method has access to the class context using this, but listener cannot be removed (there is no reference to the bounded listener as in example 2).

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

  • Alexey Sh.
    Alexey Sh. over 3 years
    SyntaxError: Unexpected token =