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

血红的双手。 提交于 2019-12-01 14:55:57

问题


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.


回答1:


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



回答2:


I was also unable to remove the listener in a class. This worked for me (see: https://nodejs.org/api/events.html#events_emitter_rawlisteners_eventname)

emitter.on('error', this.onError.bind(this));
this.onErrorListener = emitter.rawListeners('error').splice(-1)[0];
...
emitter.off('error', this.onErrorListener);



回答3:


You probably sorted this out but you could just have done

import {EventEmitter} from "events";

class HasEvents extends EventEmitter {}

const emitter = new HasEvents();


来源:https://stackoverflow.com/questions/39820651/node-js-eventemitter-how-to-bind-a-class-context-to-the-event-listener-and-then

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!