如何让一个 EventEmitter 监听 Node.js 中的另一个 EventEmitter?

mar*_*ain 5 javascript events publish-subscribe node.js 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", function(){
    console.log("emitterB detected testA");
});

emitterA.emit("testA");
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

emitterA detected testA
emitterB detected testA
Run Code Online (Sandbox Code Playgroud)

但是当我运行这段代码时,我得到的输出是:

emitterA detected testA
Run Code Online (Sandbox Code Playgroud)

我基本上希望一个发射器监听另一个发射器发射的事件。

基本原理:我正在 Node 上编写一个服务器,服务器发送 Server Sent Events。这意味着我需要持久连接。为了确保连接不会因某种原因关闭(我不想将超时设置为无穷大,因为这感觉像是黑客攻击并且看起来不安全),我发送了一个只有空白数据的心跳,只是这样正在传递给浏览器。

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

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

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

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

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

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

mic*_*nic 1

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

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

    // When everything is done emit the event to emitterB
    emitterB.emit('testA');
});
Run Code Online (Sandbox Code Playgroud)

或者,如果有多个事件要向前发出,您可以创建类似事件冒泡的东西:

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);
Run Code Online (Sandbox Code Playgroud)

PS 像这样编辑对象的方法并不是一个好的做法,但是对于一些肮脏的目的它可以很好地服务。