node lib/events.js 疑问
发布于 7 年前 作者 mario56 3730 次浏览 来自 问答

一段代码如下: 来源

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

问题

在循环执行listener时候为啥要使用 arrayClone? 不直接使用handler[i].call(self, args1)呢?

9 回复

不太清楚,可能是为了避免副作用~不过看了下源码,好像也没什么副作用,这就奇怪了。。。

@zhanzhenzhen 是的,stackoverflow 有人提到,但是感觉说的不对。

https://cnodejs.org/topic/571e0c445a26c4a841ecbcf1 楼主可以参考一下这个帖子和下面的讨论

本质上是为了避免出现递归的回调。

如果防止在一个事件监听器中监听同一个事件,接而导致死循环?

function emitOne(handler, isFn, self, arg1) {
  if (isFn)
    handler.call(self, arg1);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].call(self, arg1);//或者 handler[i].call(self, arg1);
  }
}

用户代码:

'use strict'
const EventEmitter = require('events')

let myEventEmitter = new EventEmitter()

myEventEmitter.on('wtf', function wtf () {
  myEventEmitter.on('wtf', wtf)
})

myEventEmitter.emit('wtf')

events.js 中使用 listeners[i].call(self, arg1);//或者 handler[i].call(self, arg1); 都不会导致死循环。

或许说 arrayClone 是为了防止已注册监听器的变动(如删 / 改)更合适? 引用自 @DavidCai1993

回到顶部