web-dev-qa-db-ja.com

Node.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() methodは、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のように制限されたリスナーへの参照はありません)。

別のイベントライブラリを試しました- EventEmitter イベントのカスタムコンテキストをサポートしています(クラスコンテキストは3番目のパラメーターとしてaddListener関数(_this.emitter.addListener("test", this.handleTestEvent, this_に渡すことができます) )、それは完全に機能しますが、Node.jsから含まれている EventEmitter を使用したいと思います。

10
Dominik Palo

コンストラクターでこれを行うことができます:

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

最先端を使用したい場合は、ショートカットとして 提案されたバインド演算子 を使用できます。

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

また、クラスのリスナーを削除できませんでした。これは私のために働きました(参照: 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
Jasper Kums