我想做这样的事情:
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上编写服务器,服务器发送Server Sent Events。这意味着我需要持久连接。为了确保连接由于某种原因没有关闭(我不想将超时设置为无限,因为这感觉就像一个黑客并且看起来并不安全),我发出的心跳只是空白数据,只是将某些内容传递给浏览器。
我正在运行一个计时器,并且每个时间段(在我的测试用例中为1秒),它将触发server.emit("hb");
之后我会同时写入并向所有请求对象发送数据(在我的笔记本电脑上,这只是多个标签和多个浏览器)。基本上req.on("hb", callback)
对我来说,这看起来更干净,因为替代方案是为每个请求对象提供自己的计时器,这意味着将会有许多计时器在各处运行,每个计时器都会导致其各自的请求对象发出心跳事件。这似乎是一种非理想的做事方式。
另外,因为每个请求对象都是自发创建和销毁的,所以这样做基本上可以确保创建和销毁监听器。
所以我想要的是服务器发出的心跳事件,所有活动的请求对象都会听到它并沿着自己的连接写入数据。
另一个替代方案(我现在正在使用的方法)是让服务器监听自己的事件,并让服务器编写心跳。这个问题是服务器上的maxListeners限制 - 每个请求对象都会追加一个新的" hb"侦听器到服务器,以便服务器可以侦听该特定请求对象的事件。然而,最大的听众是10,虽然我也可以将其设置为无限,但我并不太热衷于这样做,因为我真的很好奇是否有更好的方法。
对我来说,最好和最干净的解决方案似乎是制作请求对象"订阅"到服务器事件。我这样做是为了学习如何在节点中编程,所以我想尽可能少地实现外部库并使用节点的原始功能来实现,但是如果需要外部库,我很乐意阅读其源代码,以便我可以学习如何实现一个小的本地实现。
答案 0 :(得分:3)
请注意,EventEmitters是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
...
请注意,对于其他用例,您将需要使用WebSockets。 EventEmitters将无法以您希望的方式工作,尤其是远程客户端。 (socket.io
的评论确实是一个很好的起点。)
答案 1 :(得分:0)
您可以尝试将事件向前发送到元素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);
P.S。编辑像这样的对象的方法不是一个好习惯,但是出于某些肮脏的目的,它可以很好地服务。