Node.js中如何移除EventEmitter监听器?绑定场景的正确操作
如何正确移除EventEmitter中绑定了
this的监听器? 哈哈,这个问题我当初刚用EventEmitter时也踩过一模一样的坑!咱们先理清楚你给出的两种写法为什么都不对,再讲正确的做法。
首先得明确一个关键知识点:bind()方法每次调用都会返回一个全新的函数实例,不是同一个引用。
看你的代码,添加监听器时用的是this.onChange.bind(this)——这会生成一个绑定了当前this的新函数。那咱们看你纠结的两种移除方式:
- 第一种
this.listener.removeListener('eventName', this.onChange):这里传入的是原函数this.onChange,和你添加时的绑定函数不是同一个引用,EventEmitter找不到要移除的监听器,等于白调用。 - 第二种
this.listener.removeListener('eventName', this.onChange.bind(this)):这次你又调用了一次bind(),又生成了一个新的绑定函数,和之前添加的那个还是不是同一个,自然也移除不掉。
那正确的做法是什么?很简单:把绑定后的函数提前存为实例属性,添加和移除时都用这个固定的引用。
修改后的代码示例:
class MyClass { init() { this.listener = new EventEmitter(); // 把绑定后的函数存到实例上,保留引用 this.boundOnChange = this.onChange.bind(this); // 添加监听器用这个存好的绑定函数 this.listener.on('eventName', this.boundOnChange); } onChange() { /* 你的逻辑代码 */ } // 可以专门写个方法来移除监听器 cleanupListener() { // 移除时用同一个引用 this.listener.removeListener('eventName', this.boundOnChange); } }
如果你的运行环境支持ES6箭头函数,也可以用箭头函数来简化——箭头函数会自动捕获当前上下文的this,而且不需要手动bind,同样要注意存好引用:
class MyClass { init() { this.listener = new EventEmitter(); // 箭头函数自动绑定this,存好引用 this.boundOnChange = () => this.onChange(); this.listener.on('eventName', this.boundOnChange); } onChange() { /* 你的逻辑代码 */ } cleanupListener() { this.listener.removeListener('eventName', this.boundOnChange); } }
最后总结一下核心要点:
- 移除EventEmitter监听器的核心是必须传入和添加时完全相同的函数引用
- 绝对不要在
on和removeListener里分别调用bind(),因为每次bind都会生成新函数,引用不匹配 - 最佳实践是提前把绑定后的函数存为实例属性,复用同一个引用
内容的提问来源于stack exchange,提问作者Joey Yi Zhao
相关产品推荐
相关产品推荐

