最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin2浏览0评论

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.

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.

Share Improve this question edited Oct 2, 2016 at 19:53 Dominik Palo asked Oct 2, 2016 at 19:12 Dominik PaloDominik Palo 3,1115 gold badges31 silver badges55 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 14

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

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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论