Reputation: 11610
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?
Upvotes: 0
Views: 195
Reputation: 5936
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.
Upvotes: 1
Reputation: 106746
This behavior is for emit()
in general (not just the internal emitAny()
) and exists to at least prevent situations where an event handler adds itself as an event handler for the same event (or similar situations) which could cause unbounded looping for a single emit()
. For example:
emitter.on('foo', function fooHandler() {
emitter.on('foo', fooHandler);
});
Upvotes: 1