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

Nan*_*ane 8 javascript mysql node.js reactjs

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

问题:

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

我的代码库是巨大的,我面对这个错误有时我不知道为什么会发生

我尝试了什么:

试图增加听众的限制,但遗憾的是它无法正常工作.

const EventEmitter = require('events');
const emitter = new EventEmitter()
emitter.setMaxListeners(50)
Run Code Online (Sandbox Code Playgroud)

更新:

经过一些浏览后,我运行此命令来跟踪漫游

node --trace-warnings index.babel.js
Run Code Online (Sandbox Code Playgroud)

结果是我的socket.io代码是我使用socket.io与redis的问题

这是错误

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)
Run Code Online (Sandbox Code Playgroud)

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

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) => {

        let passport  = socket.handshake.session.passport;  /* To find the User Login  */
        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)})
            })


        }
    });
};
Run Code Online (Sandbox Code Playgroud)

use*_*584 15

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

默认情况下,任何单个事件最多可以注册10 个监听器,我们得到了11 个Ohno

// Change to 80 or 150 whatever and see what happens
require('events').EventEmitter.prototype._maxListeners = 70;
require('events').defaultMaxListeners = 70;

  process.on('warning', function (err) {
    if ( 'MaxListenersExceededWarning' == err.name ) {
      console.log('o kurwa');
      // write to log function
      process.exit(1); // its up to you what then in my case script was hang

    }
  });
Run Code Online (Sandbox Code Playgroud)


fli*_*tux 7

中的内置events模块node.js(如果您使用webpack或编译,则该模块的版本捆绑到您的前端应用程序中browserify)对您的代码做出一些假设。有时,在某个地方,有人认为如果您X注册了多个侦听器,那么您肯定会出现内存泄漏。有时它是正确的,并正确地提醒您去查找泄漏。

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


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

您的组件可能看起来像这样,您使用组件方法作为事件侦听器,并在注册时绑定

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
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是每次都会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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

有时你真的做了功课,仔细检查你是否根据需要提前绑定了你的听众,然后在适当的地方把它们全部删除。然后你仔细观察,发现你正在做这样的事情:

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

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

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

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

解决方案2:切换到使用 eventemitter3

如果你决定你已经完成了你的作业,并仔细检查了所有的事情,并且(按照设计!)注册了大量的事件监听器,那么最简单的解决方案是切换到 using eventemitter3,这是一个直接替代node 的events模块,除了速度更快,与浏览器兼容,并且不会为您设置最大侦听器限制。

用法就像内置events模块:

const EventEmitter = require('eventemitter3')
const emitter = new EventEmitter()
Run Code Online (Sandbox Code Playgroud)


Roh*_*ani 5

事件发射器的默认限制为10。您可以使用generator.setMaxListeners增加它。我的建议是不要更改它,除非并且直到明确要求为止,因为您没有取消订阅,因此增加了侦听器。现在到您的代码。

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) => {
    //COMMENT : This callback will be executed for all the socket connections. 
        let passport  = socket.handshake.session.passport;  /* To find the User Login  */
        if(typeof passport !== "undefined") {


            socket.on('typing:send',(data) => {

                pub.publish('spread',JSON.stringify(data))
            });
            // COMMENT : This is where you are subscribing for each and every socket conected to your server
            sub.on('message',(ch,msg) => { // this is the Exact line where I am getting this error


//COMMENT : Where as you are emiting message on socket manager not on socket. 
io.emit(`${JSON.parse(msg).commonID}:receive`,{...JSON.parse(msg)})
            })


        }
    });
};
Run Code Online (Sandbox Code Playgroud)

现在,如果我们分析以上代码,则如果您打开与服务器的20个套接字连接,它将订阅20次,这是错误的。现在,如果您的要求是在服务器级别上侦听在redis上发布的消息,然后在io上发出,则您的代码应如下所示

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 => {
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)});
        });
    io.on('connection',(socket) => {

        let passport  = socket.handshake.session.passport;  /* To find the User Login  */
        if(typeof passport !== "undefined") {


            socket.on('typing:send',(data) => {

                pub.publish('spread',JSON.stringify(data))
            });
            


        }
    });
};
Run Code Online (Sandbox Code Playgroud)