Javascript 如何使EventEmitter侦听Node.js中的另一个EventEmitter?

Javascript 如何使EventEmitter侦听Node.js中的另一个EventEmitter?,javascript,node.js,events,publish-subscribe,eventemitter,Javascript,Node.js,Events,Publish Subscribe,Eventemitter,我想这样做: var events = require("events"); var emitterA = new events.EventEmitter(); var emitterB = new events.EventEmitter(); emitterA.addListener("testA", function(){ console.log("emitterA detected testA"); }); emitterB.addListener("testA", func

我想这样做:

var events = require("events");

var emitterA = new events.EventEmitter();
var emitterB = new events.EventEmitter();

emitterA.addListener("testA", function(){
    console.log("emitterA detected testA");
});

emitterB.addListener("testA", function(){
    console.log("emitterB detected testA");
});

emitterA.emit("testA");
'use strict';
var events = require( 'events' );
//Create a new sole-source event emitter
var emitterA = new events.EventEmitter();

//create a container that can listen
function EventListener( name ) {
  console.log( 'new event listener, name=' + name );
  this.name = name;
  this.ack = function() {
    console.log( this.name + ' just heard testA' );
  };
  this.listenTo = function( event, emitter ) {
    var self = this;
    emitter.on( event, function() {
      self.ack();
    } );
  };
}

var listenerA = new EventListener( 'A', emitterA );
listenerA.listenTo( 'testA', emitterA );

var listenerB = new EventListener( 'B', emitterA );
listenerB.listenTo( 'testA', emitterA );

setInterval( function() {
  emitterA.emit( 'testA' );
}, 1000 );
输出如下:

emitterA detected testA
emitterB detected testA
但当我运行此代码时,得到的输出是:

emitterA detected testA
我基本上希望一个发射器监听另一个发射器发出的事件

理由是: 我正在节点上编写服务器,服务器发送服务器发送的事件。这意味着我需要持久连接。为了确保连接不会因为某种原因而关闭(我不想将超时设置为无穷大,因为这感觉像是黑客攻击,而且似乎不安全),我发送了一个只有空白数据的心跳信号,以便将某些信息传递给浏览器

我正在运行一个计时器,每个时间段(在我的测试用例中为1秒),它都会触发
server.emit(“hb”)之后,我同时向所有请求对象写入和发送数据(在我的笔记本电脑上,这只是多个选项卡和多个浏览器)。所以基本上
req.on(“hb”,回调)

对我来说,这似乎更干净,因为另一种方法是为每个请求对象提供自己的计时器,这意味着将有许多计时器在各处运行,每个计时器都会导致各自的请求对象发出心跳事件。这似乎是一种非最佳的做事方式

另外,由于每个请求对象都是自发创建和销毁的,这样做基本上可以确保监听器也被创建和销毁

所以我想要的是,在服务器发出的心跳事件上,所有活动的请求对象都将听到它,并沿着它们自己的连接写入数据

另一种选择(我现在正在使用的方法)是让服务器监听自己的事件,并让服务器写入心跳。这方面的问题是服务器上的maxListeners限制——每个请求对象都将向服务器附加一个新的“hb”侦听器,以便服务器可以侦听该特定请求对象的事件。不过,最大侦听器是10,虽然我也可以将其设置为无穷大,但我并不太热衷于这样做,因为我真的很好奇是否有更好的方法


对我来说,最好、最干净的解决方案似乎是让请求对象“订阅”服务器事件。我这样做是为了学习如何在node中编程,所以我希望实现尽可能少的外部库,并使用node的原始功能来实现,但如果需要外部库,我很乐意阅读它的源代码,以便学习如何实现小型本地实现。

您可以尝试将事件转发到元素
emitterB

emitterA.addListener("testA", function(){
    console.log("emitterA detected testA");

    // When everything is done emit the event to emitterB
    emitterB.emit('testA');
});
或者,如果有多个事件要向前发射,则可以创建类似事件冒泡的内容:

function bubbleEvents(from, to) {

    var oldEmit = from.emit;

    from.emit = function (event) {

        var args = Array.prototype.slice.call(arguments, 1),
            newArgs = [event].concat(args);

        oldEmit.apply(from, newArgs);
        to.emit.apply(to, newArgs);
    };
}

// and call it
bubbleEvents(emitterA, emitterB);

另外,编辑这样一个对象的方法不是一个好的做法,但对于一些不好的目的,它可以很好地发挥作用。

注意,EventEmitter是javascript中唯一的源代码。它们不是每个人都能听到的全系统事件。它们是可以发出事件以支持异步模式的对象。为了实现您想要的,您需要多个东西来监听同一个发射器。大概是这样的:

var events = require("events");

var emitterA = new events.EventEmitter();
var emitterB = new events.EventEmitter();

emitterA.addListener("testA", function(){
    console.log("emitterA detected testA");
});

emitterB.addListener("testA", function(){
    console.log("emitterB detected testA");
});

emitterA.emit("testA");
'use strict';
var events = require( 'events' );
//Create a new sole-source event emitter
var emitterA = new events.EventEmitter();

//create a container that can listen
function EventListener( name ) {
  console.log( 'new event listener, name=' + name );
  this.name = name;
  this.ack = function() {
    console.log( this.name + ' just heard testA' );
  };
  this.listenTo = function( event, emitter ) {
    var self = this;
    emitter.on( event, function() {
      self.ack();
    } );
  };
}

var listenerA = new EventListener( 'A', emitterA );
listenerA.listenTo( 'testA', emitterA );

var listenerB = new EventListener( 'B', emitterA );
listenerB.listenTo( 'testA', emitterA );

setInterval( function() {
  emitterA.emit( 'testA' );
}, 1000 );
产出:

$ node testfile.js 
new event listener, name=A
new event listener, name=B
A just heard testA
B just heard testA
A just heard testA
B just heard testA
...

请注意,对于其他用例,您将希望使用WebSocket。EventEmitter将无法按您希望的方式工作,特别是对于远程客户端。(对
socket.io
的评论确实是一个很好的开始。)

仅供参考,
socket.io
已经解决了与节点服务器的持久连接问题,并且内置了消息传递范例,使用非常方便。您可以使用it客户端到服务器或服务器到服务器。我不是在连接中使用事件,只是在同一个模块中使用它们来使不同的对象通信。如果您不在连接中执行事件,为什么您的问题是“持久连接”和“热节拍”?对我来说毫无意义。呃,对不起,你是对的。我应该澄清一下——我没有尝试使用//Websockets/,所以我不打算从服务器传输一个可以从客户端听到的事件。我很欣赏socket.io有多棒,但是在玩node的时候,我也会看看SSEs。因此,我尝试在服务器中创建一个事件,服务器中的另一个侦听器可以听到该事件。这不是产品化,而是好奇心。对不起,如果这是一个否决票,先生…这是好的,但它必须创建一个新的对象每次。我希望每个请求对象(它是自发创建和销毁的)都只是监听,而这些侦听器会随着请求对象一起消亡。我会再编辑一点我的帖子这个对象只是一个例子。关键是事件发射器必须共享。您可以在服务器启动时对其进行初始化,或者在每个请求上使用一些中间件来订阅(或“附加”)该全局发射器。不过请记住,EventEmitter是唯一的源代码,而不是发布-订阅。为此,你可能需要一些额外的东西(请参阅),或者找一个图书馆,甚至。