Node.js EventEmitter:如何将类上下文绑定到事件侦听器,然后删除此侦听器

时间:2016-10-02 19:12:46

标签: javascript node.js events typescript eventemitter

有没有办法在事件监听器方法中访问类上下文,并有可能删除监听器?

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

在此示例中,删除侦听器有效,但handleTestEvent()方法无法使用this访问类上下文。 this指向EventEmitter上下文,因此无法访问this.text

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

在这个例子中,我使用bind函数将类的上下文绑定到事件侦听器。现在handleTestEvent方法可以使用this =>访问类上下文可以访问this.text,但无法使用removeListener删除侦听器 - bind似乎创建了一个新的匿名函数,因此没有对有界侦听器的引用。

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

在这个例子中,我使用箭头函数来保留事件监听器中类的上下文。 handleTestEvent方法可以使用this访问类上下文,但无法删除侦听器(没有像示例2那样引用有界侦听器)。

我尝试过另一个事件库 - EventEmitter3,它支持事件的自定义上下文(类上下文可以作为第三个参数传递给addListener函数(this.emitter.addListener("test", this.handleTestEvent, this) ,它工作得很好,但我宁愿使用Node.js中包含的EventEmitter

3 个答案:

答案 0 :(得分:7)

您可以在构造函数中执行此操作:

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

如果您想使用最前沿,可以使用proposed bind operator作为快捷方式:

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

或使用property initializer创建绑定方法:

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

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

handleTestEvent = () => {
  console.log(this.text);
}

答案 1 :(得分:0)

我也无法删除课程中的侦听器。这对我有用(请参阅: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);

答案 2 :(得分:-1)

你可能已经对此进行了整理,但你可能已经完成了

import {EventEmitter} from "events";

class HasEvents extends EventEmitter {}

const emitter = new HasEvents();