在Node.js中,是否正在监听EventEmitter,创建对它的引用?

时间:2016-07-19 03:45:32

标签: javascript node.js memory-management garbage-collection eventemitter

如果我有这样的代码:

const EventEmitter = require('events');

class Bot extends EventEmitter {
  sendMessage() {
    // do something
    this.emit('messageSent', 'user123');
  }
}

class Controller {
  loadBot() {
    const bot = new Bot();
    bot.on('messageSent', userId => {
      // do something
    });
  }
}

bot内创建的loadBot对象会立即被销毁吗?或者稍后通过垃圾收集?

或者Controller的实例是否会引用它,以便在bot实例被销毁之前永远不会销毁Controller

2 个答案:

答案 0 :(得分:4)

单独注册一个事件监听器并不能防止它被垃圾回收。有些东西实际上必须引用Bot对象本身(以便实际上可以从它发出事件),因为它不会被垃圾收集。

在Controller类中,如果没有其他内容可以引用您创建的Bot实例,那么它将有资格进行垃圾回收。这是有道理的,因为如果没有任何引用它,那么没有别的东西可以使用它,也没有任何东西可以调用它的自定义方法sendMessage()

现在有了代码,bot变量只是loadBot()方法中的局部变量,没有其他内容可以引用它。因此,只要loadBot()方法执行完毕,bot变量就有资格进行垃圾收集,因为任何地方都没有代码可以再次使用或到达该对象。这使它有资格进行垃圾收集。

从您的代码中,您可能认为bot变量可能是Controller对象的实例变量。如果是这种情况,那么只要有人引用了您的Controller对象,那么bot对象也会保持活跃状态​​。

所以,看起来好像你打算这样做:

const EventEmitter = require('events');

class Bot extends EventEmitter {
  sendMessage() {
    // do something
    this.emit('messageSent', 'user123');
  }
}

class Controller {
  loadBot() {
    this.bot = new Bot();
    this.bot.on('messageSent', userId => {
      // do something
    });
  }

  send() {
      this.bot.sendMessage();
  }
}

var c = new Controller();
c.loadBot();

这里保留对bot对象的实例数据中Controller变量的引用,因此可以通过其他代码(如send()方法)或任何其他代码访问它用于访问.bot对象上的Controller属性的代码。

答案 1 :(得分:0)

我不认为对象 bot 将被GC,因为有一个侦听器持有对该对象的引用。