Javascript NodeJS:一个全局事件发射器或它的每个模块';他自己的?

Javascript NodeJS:一个全局事件发射器或它的每个模块';他自己的?,javascript,node.js,performance,events,Javascript,Node.js,Performance,Events,我目前正计划在NodeJS中创建一个浏览器游戏。游戏将使用事件进行模块之间的基本每次通信 什么性能更好(或有优点或缺点?) 我只使用一个(全局?)EventEmitter。每个模块都可以侦听该全局事件流或在全局事件流中发出事件。我将使用更复杂的事件名称,因此当触发事件时,不会调用全局事件流上的所有侦听器。我在一个事件流中有大量的侦听器 示例:Player1接收一个项目。触发事件“player1:inventory:item”,并且只有player1在全局事件流上侦听该事件 或 它自己的每个模块都

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

什么性能更好(或有优点或缺点?) 我只使用一个(全局?)EventEmitter。每个模块都可以侦听该全局事件流或在全局事件流中发出事件。我将使用更复杂的事件名称,因此当触发事件时,不会调用全局事件流上的所有侦听器。我在一个事件流中有大量的侦听器

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

或 它自己的每个模块都扩展了events.EventEmitter,并且只提供该特定对象的事件。每个EventEmitter上的侦听器数量非常少,大多数情况下只有一个侦听器

示例:单个玩家有一个questlog和一个清单。我为每个玩家创建了一个questlog和inventory的实例,将它们保存在一个集合(或玩家对象)中。player1的任务日志只侦听player1的资源清册


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

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


谢谢你的帮助

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

 var EventEmitter = require('events').EventEmitter;
 var util = require('util');

 function YouEmitter() {
     EventEmitter.call(this);
 }
 util.inherits(YourEmitter, EventEmitter);
有很多理由这样做,但很少有具有确凿事实背景的资源。一个很好的可能是Mozilla的

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

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

  • 最后,你的应用迟早会崩溃。你可以打赌,当你越来越受欢迎的时候,这种事情就会发生。然后每个人都会在黑客新闻中嘲笑你,说你的坏话,你会很伤心

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

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

    另一个原因是,调试内存泄漏和相关故障对调试来说并不简单(从我在上面看到的情况来看)。 当eventemitter泄漏时,它会变得非常危险,因为它会阻塞事件循环

    许多其他基于事件的库都喜欢并允许它们的事件客户端接收所有发出的事件。他们将通过模式来确定自己的行为是否应该是一个动作,例如事件的有效负载对他们来说是否有趣或者ID是否匹配等等

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


    这取决于应用程序中使用的事件样式或事件样式的组合。如果使用广播样式,其中多个订阅者订阅一个频道/主题,多个发布者发布该频道/主题,那么EventEmitter实例必须位于其发布者和订阅者的“全局”中。对于广播风格,出版商和订阅者都不需要相互了解

    如果事件处理更为点对点的方式,即每个订阅服务器订阅其引用的发布服务器,则订阅服务器必须了解发布服务器,并且发布服务器必须在发布服务器之前实例化

    这两种样式都可以通过全局单例EventEmitter(使用事件名称空间)或每模块EventEmitter实现,但全局EventEmitter更适合广播样式,而每模块EventEmitter更适合点到点

    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');