在 nodejs/events.js 的 emitMany 函数中克隆监听器数组的原因是什么?
What is the reason for cloning the listeners array in nodejs/events.js' emitMany function?
函数代码(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);
}
}
这一行:
var listeners = arrayClone(handler, len);
克隆了在此范围内命名为 handler
的侦听器数组,然后将其克隆分配给名为 listeners
的新变量。我想知道这有什么用。
我怀疑这是因为侦听器可以从列表中删除自己,并且该操作会破坏 for 循环中的计数器(列表项的索引在删除后会更改,但计数器 i
会盲目地继续不知道这一点)。
我的解释是否正确,或者可能有什么问题else/more?
此行为一般适用于 emit()
(而不仅仅是内部 emitAny()
)并且至少可以防止事件处理程序将自己添加为同一事件(或类似情况),这可能会导致单个 emit()
的无限循环。例如:
emitter.on('foo', function fooHandler() {
emitter.on('foo', fooHandler);
});
那是因为当发出相应的事件时,处理程序可能会为该事件添加/删除处理程序,从而修改迭代的数组。
foo.on('bar', function() {
foo.on('bar', function() { // should not be invoked now / but for the next and subsequent events
})
})
第一次触发 'bar' 事件时不应调用第二个处理程序,因此必须在执行处理程序之前克隆处理程序数组。
函数代码(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);
}
}
这一行:
var listeners = arrayClone(handler, len);
克隆了在此范围内命名为 handler
的侦听器数组,然后将其克隆分配给名为 listeners
的新变量。我想知道这有什么用。
我怀疑这是因为侦听器可以从列表中删除自己,并且该操作会破坏 for 循环中的计数器(列表项的索引在删除后会更改,但计数器 i
会盲目地继续不知道这一点)。
我的解释是否正确,或者可能有什么问题else/more?
此行为一般适用于 emit()
(而不仅仅是内部 emitAny()
)并且至少可以防止事件处理程序将自己添加为同一事件(或类似情况),这可能会导致单个 emit()
的无限循环。例如:
emitter.on('foo', function fooHandler() {
emitter.on('foo', fooHandler);
});
那是因为当发出相应的事件时,处理程序可能会为该事件添加/删除处理程序,从而修改迭代的数组。
foo.on('bar', function() {
foo.on('bar', function() { // should not be invoked now / but for the next and subsequent events
})
})
第一次触发 'bar' 事件时不应调用第二个处理程序,因此必须在执行处理程序之前克隆处理程序数组。