【问题标题】:How to call remove listener on EventEmitter in nodejs?如何在 nodejs 中的 EventEmitter 上调用删除侦听器?
【发布时间】:2026-01-23 01:00:01
【问题描述】:

我有以下代码可以在EventEmitter 上添加监听器,

class MyClass {
  init() {
    this.listener = new EventEmitter();
    this.listener.on('eventName', this.onChange.bind(this));
  }
  onChange() {
    ...
  }
}

如何从EventEmitter 中删除监听器?我可以看到两种不同的方式:

this.listener.removeListener('eventName', this.onChange)
this.listener.removeListener('eventName', this.onChange.bind(this))

我想知道我应该使用哪一个。删除时是否需要bind

【问题讨论】:

标签: node.js eventemitter


【解决方案1】:

您可以使用 bind() 或在 Node.js 中使用 Arrow Function。箭头函数将从调用上下文继承它们的执行上下文,这类似于bind() 的工作方式并提供相同的功能。

this.listener.removeListener('eventName', this.onChange)

如果在removeListener(eventName) 样式函数中调用它,则上述删除侦听器的方法将不起作用,如下所示:

const obj = new MyObject()
obj.init()
// This would blow up with a 
// ReferenceError saying you cant call removeListener() on undefined   
obj.listener.removeListener('event') 

当您可以使用 constructorclass 语法时,不确定是否使用 init() 函数。

constructor() {
  this.listener = new EventEmitter()
  this.boundEventNameHandler = () => this.onChange()
  this.listener.on('eventName', this.boundEventNameHandler)
}

您可以使用绑定函数在使用this 的类的上下文中删除侦听器。

let boundEventNameHandler = this.boundEventNameHandler
this.listener.removeListener('eventName', this.boundEventNameHandler)`

实现的示例如下所示

const EventEmitter = require('events')

class MyObject {
  constructor () {
    this.listener = new EventEmitter()
    this.boundEventNameHandler = () => this.onChange()
    this.listener.on('eventName', this.boundEventNameHandler)
  }

  // I would reconsider making this a property of the MyObject class 
  // instead, make onChange() a local function outside the MyObject 
  // class definition because onChange in this example is only used by the 
  // event listener for 'eventName' 
  onChange () {
    console.log('event fired change')
  }

  removeListeners () {
    let boundEventNameHandler = this.boundEventNameHandler
    this.listener.removeListener('eventName', boundEventNameHandler)
  }
}

【讨论】:

  • 这是错误的。它不能以这种方式工作,并且不会删除侦听器,因为您实际上在 .on 和 .removeListener 中声明了两个不同的 lambda 函数。
  • @user0103 很好地解决了removeListener() 的函数指针问题。更新以存储对函数指针的引用。在这种情况下,您可以使用箭头函数或.bind(this)
【解决方案2】:

对于 TypeScript / ESNext,你可以使用这个:

class MyClass {
    constructor() {
        this.emitter = new EventEmitter();

        this.emitter.on("event1", this.listener1);
        this.emitter.on("event2", this.listener2);

        this.emitter.removeListener("event1", this.listener1);
        this.emitter.removeListener("event2", this.listener2);

        this.emitter.emit("event1"); // no output
        this.emitter.emit("event2"); // no output
    }

    public listener1 = (e) => {
        console.dir(`listener1`);
    };

    public listener2 = (e) => {
        console.dir(`listener2`);
    };
}  

基本上,您定义属性并立即为它们分配绑定函数。
这样您就可以在.on.removeListener 中使用相同的函数引用。

【讨论】: