javascript - Node.js EventEmitter: Hur man binder en klasskontext till händelselyssnaren och sedan tar bort denna lyssnare


Finns det ett sätt att få tillgång till klassens kontext i metod för händelselyssnare med möjlighet att ta bort lyssnaren?

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

I det här exemplet fungerar det att ta bort lyssnaren, men handleTestEvent()-metoden har ingen tillgång till klassens kontext med this. this pekar på EventEmitter-kontexten, så this.text är inte åtkomligt.

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

I detta exempel använder jag bind-funktionen för att binda ett klasskontext till händelselyssnaren. Nu har handleTestEvent-metoden tillgång till klasskontexten med this => this.text är åtkomligt, men lyssnaren kan inte tas bort med removeListener - det verkar som att bind skapar en ny anonym funktion, så det finns ingen referens till den bundna lyssnaren.

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

I det här exemplet använder jag en pilfunktion för att bevara klassens kontext i händelselyssnaren. handleTestEvent-metoden har åtkomst till klasskontexten med hjälp av this, men lyssnaren kan inte tas bort (det finns ingen referens till den bundna lyssnaren som i exempel 2).

Jag har provat ett alternativt evenemangsbibliotek - EventEmitter3 som har stöd för anpassad kontext för evenemang (klasskontext kan skickas som tredje parameter till addListener-funktionen (this.emitter.addListener("test", this.handleTestEvent, this), det fungerar perfekt, men jag vill hellre använda den medföljande EventEmitter från Node.js.

Svar #1

Du kan göra detta i konstruktorn:

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

Om du vill använda den senaste tekniken kan du använda den föreslagna bindeoperatorn som en genväg:

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

Eller använd en egenskapsinitialiserare för att skapa en bunden metod:

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

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

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

Relaterade artiklar