Node.js EventEmitter:如何将 class 上下文绑定到事件侦听器,然后删除此侦听器
Node.js EventEmitter: How to bind a class context to the event listener and then remove this listener
有没有办法在事件侦听器方法中访问 class 上下文并有可能删除侦听器?
示例 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
访问 class 上下文。 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
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
- 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);
}
}
在此示例中,我使用箭头函数在事件侦听器中保留 class 的上下文。 handleTestEvent
方法可以使用 this
访问 class 上下文,但无法删除侦听器(没有对示例 2 中的有界侦听器的引用)。
我尝试了另一个事件库 - 来自 Node.js 的 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。
您可以在构造函数中执行此操作:
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);
}
我也无法在 class 中删除侦听器。这对我有用(参见: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);
有没有办法在事件侦听器方法中访问 class 上下文并有可能删除侦听器?
示例 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
访问 class 上下文。 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
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
- 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);
}
}
在此示例中,我使用箭头函数在事件侦听器中保留 class 的上下文。 handleTestEvent
方法可以使用 this
访问 class 上下文,但无法删除侦听器(没有对示例 2 中的有界侦听器的引用)。
我尝试了另一个事件库 - 来自 Node.js 的 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。
您可以在构造函数中执行此操作:
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);
}
我也无法在 class 中删除侦听器。这对我有用(参见: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);