NodeJS:一个全局EventEmitter或每个模块它'他自己的

NodeJS: One Global EventEmitter or every module it's own?

本文关键字:模块 他自己 自己的 EventEmitter 一个 NodeJS 全局      更新时间:2023-09-26

我目前正计划在NodeJS中创建一个浏览器名称。游戏将使用事件进行模块之间的基本每次通信。

什么更具性能(或有优点或缺点?):

我只使用一个(全局?)EventEmitter。每个模块都可以侦听该全局事件流或在全局事件流中发出事件。我会使用更复杂的事件名称,所以当事件被触发时,并不是全局事件流上的所有侦听器都被调用。我在一个事件流中有大量的听众。

示例:Player1接收一个项目。事件"player1:inventory:item"被激发,并且只有player1在全局事件流上侦听该事件。

每个模块本身都扩展了事件。EventEmitter,并且只提供该特定对象的事件。每个EventEmitter上的侦听器数量非常少,大多数时候只有一个侦听器。

示例:一个玩家有一个任务日志和一个库存。我为每个玩家创建一个questlog和inventory的实例,将它们保存在一个集合(或玩家对象)中。播放器1的questlog只监听播放器1的库存。


我没有在NodeJS中使用EventEmitter的经验,只知道当一个事件发射器或事件上由于内存泄漏而有超过10个侦听器时会发出警告,但我不知道为什么。

我看到了这两种系统的一些优点和缺点,但在技术方面我需要建议。

谢谢你的帮助!

这取决于您在应用程序中使用的事件样式或事件样式的组合。如果你使用的广播风格是多个订阅者订阅一个频道/主题,而多个发布者发布到该频道/主题上,那么EventEmitter实例必须生活在";全局";向其出版商和订阅者提供。对于广播风格,出版商和订户都不需要了解彼此。

如果您的事件处理是点对点的风格,每个订阅者都订阅了它引用的发布者,那么订阅者必须知道发布者,并且订阅者必须在发布者之前实例化。

这两种风格都可以通过全局单例EventEmitter(使用事件名称空间)或每个模块的EventEmitter来实现,但全局EventEmitter更自然地适合广播风格,每个模块的EventEmitter对点对点更自然。

我认为为您的模块扩展Eventemitter肯定更好。你会这样做的。这是模块编写器的常见模式。

 var EventEmitter = require('events').EventEmitter;
 var util = require('util');
 function YouEmitter() {
     EventEmitter.call(this);
 }
 util.inherits(YourEmitter, EventEmitter);

有很多理由这样做,但很少有资源和确凿的事实背景。一个非常好的可能是Mozilla的节点整体季系列。

  1. 您可能不担心内存占用量的增加,但V8确实如此。(V8是Node运行的引擎。)随着泄漏的增加,V8在垃圾收集方面变得越来越激进,从而降低了应用程序的速度。因此,在Node中,内存泄漏会影响性能。

  2. 泄漏可能引发其他类型的故障。泄漏的代码可能会保留对有限资源的引用。您可能会用完文件描述符;您可能突然无法打开新的数据库连接。这类问题可能早在你的应用程序内存耗尽并让你陷入困境之前就出现了。

  3. 最后,你的应用迟早会崩溃。你可以打赌,它会在你变得受欢迎的那一刻发生。然后每个人都会笑着在黑客新闻上说你的刻薄话,你会很难过。

除了垃圾回收,其他组件的随机故障,我认为最后一点是最有趣的:它可能是糟糕的风格。当Node与之相反时,它会使你的应用程序变得沉重。

同时调用调用构造函数也是非常昂贵的。

另一个原因是调试内存泄漏和相关故障并不是一件小事(从我在SO上看到的情况来看)。当eventemitter泄漏时,它真的会失控,因为它会阻塞事件循环。

许多其他基于事件的库,如Seneca和ZMQ,都允许它们的事件客户端接收所有发出的事件。他们将通过模式来确定他们的行为是否应该是一个行为,例如事件的有效负载是否对他们感兴趣或ID是否匹配等。

在您的情况下,通过事件名称进行区分可能是最简单的(类似这样的):

var EventEmitter = require('events').EventEmitter;
var ee = new EventEmitter();
var eNR2 = '2';
ee.on('event'+ eNR2, function(){ console.log('Event 2 has fired!')});
ee.emit('event2');