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

The built-in events module in node.js (a version of which is bundled into your frontend app if you compile with webpack or browserify) makes some assumptions about your code. Sometime, somewhere, somebody decided that if you had X number of listeners registered, then surely you’ve got a memory leak. And sometimes it is correct, and reminds you correctly to go find the leaks.

I’ve received this warning many times, but usually only for two specific reasons, both of which have simple solutions:


Problem 1: Mismatched bound event listener functions

Your component may look like this, where you are using a component method as the event listener, and you are binding it as you register it.

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
  }
}

The problem here is that function.bind creates a new function each time, such that the function you are trying to remove is not the same as the function you added. Consequently, the added functions keep adding-up (bad pun), and you do in fact have a real memory leak.

Solution 1: Bind your methods early

Bind your method early, commonly in the constructor(). Then you can refer to the bound version each time, ensuring that the function removed is the same as the function added.

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
  }
}

Problem 2: Lots and lots of event listeners

Sometimes you’ve really done your homework and double-checked that you’ve bound your listeners early as needed, and then removed them all at the appropriate places. Then you look closer and find that you’re doing something like this:

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 had 50, 100, or maybe 250 elements. This means that (by design!) you are rendering 250 instances of MyComponent, each of which is registering another unique event listener.

Fear not! This is totally valid code, and does not have a memory leak. But it does blow through the max-listeners limit that somebody, sometime, somewhere decided arbitrarily to help protect you.

Solution 2: Switch to using eventemitter3

If you decide that you’ve done your homework, and double-checked all the things, and are (by design!) registering lots of event listeners, then the simplest solution is to switch to using eventemitter3, which is a drop-in replacement for node’s events module, except faster, and browser-compatible, and doesn’t set a max-listeners limit for you.

Usage is just like the built-in events module:

const EventEmitter = require('eventemitter3')
const emitter = new EventEmitter()

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)