javascript - 如何让 EventEmitter 监听 Node.js 中的另一个 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", function(){
    console.log("emitterB detected testA");
});

emitterA.emit("testA");

输出是这样的:

emitterA detected testA
emitterB detected testA

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

emitterA detected testA

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

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

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

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

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

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

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

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

最佳答案

请注意,EventEmitter 是 javascript 中的唯一来源。它们不是每个人都可以收听的系统范围的事件。它们是可以发出事件以支持异步模式的对象。为了完成你想要的,你需要多个东西听同一个发射器。像这样:

'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 的评论确实是一个很好的起点。)

关于javascript - 如何让 EventEmitter 监听 Node.js 中的另一个 EventEmitter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26465358/

相关文章:

java - 将按键发送到 JTextField

ios - 监听 iOS 截屏事件

javascript - 当select只有一项时如何禁用select的下拉菜单

javascript - pinterest 是如何实现其布局的?

javascript - jQuery load() 不加载正在加载的 html 文件内的图像链接?

node.js - 使用node.js和mongoDB向map.jade文件(传单)添加标记

javascript - 通过 JavaScript 动态创建 CSS 关键帧动画

javascript - 在 Node.js 上运行多个物理世界,但没有充分利用服务器

javascript - 将获取请求从一个 node.js 服务器转发到另一个

c# - Lambda 表达式和事件订阅