Узел.JS 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 который поддерживает пользовательский контекст для событий (контекст класса может быть передан в качестве третьего параметра в

2 ответов


вы можете сделать это в конструкторе:

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

Если вы хотите использовать передний край, вы можете использовать предлагаемый оператор bind как ярлык:

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

или использовать собственность инициализатора чтобы создать связанный метод:

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

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

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

вы, вероятно, разобрались в этом, но вы могли бы просто сделать

import {EventEmitter} from "events";

class HasEvents extends EventEmitter {}

const emitter = new HasEvents();