MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。添加了 11 条消息列表。使用emitter.setMaxListeners()来增加限制

2024-06-20

我知道这可能会标记为重复的解决方案,但堆栈溢出的解决方案对我不起作用。

Problem

(node:5716) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message lis
teners added. Use emitter.setMaxListeners() to increase limit.

我的代码库很大,有时我会遇到这个错误,我不知道为什么会发生。我尝试增加听众限制,但不幸的是,它不起作用。

const EventEmitter = require('events');
const emitter = new EventEmitter()
emitter.setMaxListeners(50)

UPDATE

经过一番浏览后,我运行此命令来跟踪警告

node --trace-warnings index.babel.js

事实证明,我的 socket.io 代码是我在 Redis 中使用 socket.io 时出现的问题。这是错误

node:14212) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message li
steners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:281:19)
    at RedisClient.addListener (events.js:298:10)
    at Namespace.<anonymous> (D:/newProject/services/socket.js:21:17)
    at emitOne (events.js:115:13)
    at Namespace.emit (events.js:210:7)
    at Namespace.emit (D:\newProject\node_modules\socket.io\lib\namespace.js:213:10)
    at D:\newProject\node_modules\socket.io\lib\namespace.js:181:14
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

这是代码(但此代码用于更具体的任务,它不会一直执行)。

const redis = require('redis');
const config = require('../config');
const sub = redis.createClient(config.REDIS.port, config.REDIS.host);
const pub = redis.createClient(config.REDIS.port, config.REDIS.host);

sub.subscribe('spread');

module.exports = io => {
  io.on('connection', socket => {
    /* To find the User Login  */
    let passport = socket.handshake.session.passport; 

    if (typeof passport !== 'undefined') {
      socket.on('typing:send', data => {
        pub.publish('spread', JSON.stringify(data));
      });

      sub.on('message', (ch, msg) => {
        // This is the Exact line where I am getting this error
        io.emit(`${JSON.parse(msg).commonID}:receive`, { ...JSON.parse(msg) });
      });
    }
  });
};

内置的events https://devdocs.io/node~8_lts/events模块输入node.js https://nodejs.org/(如果您使用以下命令进行编译,则该版本将捆绑到您的前端应用程序中webpack https://webpack.js.org/ or browserify http://browserify.org/)对您的代码做出一些假设。某个时候,某个地方,有人决定如果你有X注册的听众数量,那么surely你有内存泄漏。有时它是正确的,并正确地提醒你去寻找泄漏点。

我多次收到此警告,但通常只有两个特定原因,这两个原因都有简单的解决方案:


问题1:绑定事件监听器函数不匹配

您的组件可能如下所示,其中您使用组件方法作为事件侦听器,并且绑定它当你注册时.

import events from '../lib/events' // some singleton event emitter

class MyComponent extends React.Component {
  componentDidMount() {
    events.addEventListener('some-event', this.myMethod.bind(this))
  }

  componentWillUnmount() {
    events.removeEventListener('some-event', this.myMethod.bind(this))
  }

  myMethod() {
    // does something
  }

  render() {
    // gotta have this too
  }
}

这里的问题是function.bind https://devdocs.io/javascript/global_objects/function/bind创建一个新功能每次,您尝试删除的功能都与您添加的功能不同。因此,添加的函数不断增加(不好的双关语),并且实际上确实存在内存泄漏。

解决方案 1:尽早绑定您的方法

尽早绑定你的方法,通常在constructor()。然后每次都可以参考绑定的版本,确保移除的功能与添加的功能相同。

import events from '../lib/events' // some singleton event emitter

class MyComponent extends React.Component {
  constructor() {
    // bind your method early so the function removed
    // is the same as the function added
    this.myMethod = this.myMethod.bind(this)
  }

  componentDidMount() {
    events.addEventListener('some-event', this.myMethod)
  }

  componentWillUnmount() {
    events.removeEventListener('some-event', this.myMethod)
  }

  myMethod() {
    // does something
  }

  render() {
    // gotta have this too
  }
}

问题 2:大量的事件监听器

有时,您确实做了功课,并仔细检查了是否已根据需要尽早绑定了听众,然后将它们全部删除在适当的位置。然后你仔细观察,发现你正在做这样的事情:

import MyComponent from './MyComponent' // same component above

class Parent extends React.Component {
  render() {
    return (
      <div>
        { this.props.largeArray.map(MyComponent) }
      </div>
    )
  }
}

Suppose this.props.largeArray有 50 个、100 个或可能 250 个元素。这意味着(按照设计!)您正在渲染 250 个实例MyComponent,每个都注册另一个唯一的事件侦听器。

不要害怕!这是完全有效的代码,并且没有内存泄漏。但它确实突破了某人在某个时间、某个地方任意决定帮助保护你的最大听众限制。

解决方案 2:切换到使用eventemitter3 https://www.npmjs.com/package/eventemitter3

如果您确定已经完成了作业,并仔细检查了所有内容,并且(按设计!)注册了大量事件侦听器,那么最简单的解决方案是切换到使用eventemitter3 https://www.npmjs.com/package/eventemitter3,这是节点的直接替代品events模块,除了速度更快,并且与浏览器兼容,并且不会为您设置最大侦听器限制。

使用方法和内置的一样events module:

const EventEmitter = require('eventemitter3')
const emitter = new EventEmitter()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。添加了 11 条消息列表。使用emitter.setMaxListeners()来增加限制 的相关文章

随机推荐