Search code examples
javascriptnode.jseventemitter

What is the reason for cloning the listeners array in nodejs/events.js' emitMany function?


The function code (source code on github):

function emitMany(handler, isFn, self, args) {
  if (isFn)
    handler.apply(self, args);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].apply(self, args);
  }
}

In this line:

var listeners = arrayClone(handler, len);

an array of listeners, named in this scope as handler, is cloned, and then its clone is assigned to a new variable named listeners. I wonder what is this useful for.

I suspect it's because a listener can remove itself from the list, and that action would break the counter in the for loop (the list items' indexes would change after the removal, but the counter i would blindly keep going unaware of that).

Is my explanation correct, or maybe there's something else/more to it?


Solution

  • that's because when the respective event is emitted, the handler might add / remove handlers for that very event thus modifying the array which is iterated.

    foo.on('bar', function() {
      foo.on('bar', function() { // should not be invoked now / but for the next and subsequent events
      })
    })
    

    the second handler should not be called when the 'bar' event is fired the first time, thus the array of handlers must be cloned before executing the handlers.