[英]Forwarding events from one event emitter to another
我有一个事件发射器(一个变换流),该事件发射器基本上有一堆子发射器。
我想将所有子发射器中的事件转发到父发射器,如下所示:
const EE = require('events');
const exportEvents = new EE();
const sumanEvents = Transform(); // create new transform stream (an event emitter)
sumanEvents.on('test', function () {
exportEvents.emit.bind(exportEvents, 'test').apply(exportEvents, arguments);
});
sumanEvents.on('error', function () {
exportEvents.emit.bind(exportEvents, 'error').apply(exportEvents, arguments);
});
sumanEvents.on('suman-test-file-complete', function () {
exportEvents.emit.bind(exportEvents, 'suman-test-file-complete').apply(exportEvents, arguments);
});
基本上,根据我的判断,我已将错误,测试和suman-test-file-complete事件转发给父级,但这看起来非常难看。
至少有一种更复杂的方式吗? 我假设没有办法直接用Node.js'events'包继承事件,所以我不是在问这个问题。
您可以覆盖sumanEvents.emit()
这样您就可以看到发出的任何事件,然后抓住它并将其回显给exportEvents
:
(function(origEmitter, forwardEmitter) {
// save original .emit method
let oldEmit = origEmitter.emit;
// assign override
origEmitter.emit = function() {
// allow the event to be normally emitted
oldEmit.apply(origEmitter, arguments);
// then forward it to the forwardEmitter
forwardEmitter.emit.apply(forwardEmitter, arguments);
};
})(sumanEvents, exportEvents);
或者,放入一个可重复使用的函数表单,以便您可以在多个发射器上使用它而无需复制代码:
function forwardEmitter(origEmitter, forwardEmitter) {
// save original .emit method
let oldEmit = origEmitter.emit;
// assign override
origEmitter.emit = function() {
// allow the event to be normally emitted
oldEmit.apply(origEmitter, arguments);
// then forward it to the forwardEmitter
forwardEmitter.emit.apply(forwardEmitter, arguments);
};
}
forwardEmitter(sumanEvents, exportEvents);
如果你想更容易地重用它,可以将这个功能封装在一个派生自EventEmitter
的新对象中,但这只有在你控制第一个EventEmitter对象的创建时才有效,所以你可以把它作为你的特殊派生对象支持转发所有消息。 上面的示例可以“添加”到任何现有的常规EventEmitter
对象。
此处还描述了一个EventEmitter2
对象,允许您使用通配符注册事件处理程序,这样您就可以注册所有事件或事件子集的兴趣,而无需单独命名每个事件。
并且,在Google邮件列表上讨论了这个概念: https : //groups.google.com/forum/#!topic / nodejs-dev / TzRPxsHf0FA
但这看起来很难看。
你是否有约束力并申请? 似乎这些使用不正确。 诸如exportEvents.emit.bind(exportEvents, 'test').apply(exportEvents, arguments)
可以简化为EE.emit.apply(exportEvents, 'test', arguments)
或者使用扩展语法exportEvents.emit('test', ...arguments)
话虽如此,实用功能在这里可能会有所帮助。 jfriend00上面的解决方案没问题,但我真的不喜欢它覆盖原始对象上的方法(即使调用原始方法)。
另一个解决方案实际上更简单(更少的代码行):
function forwardEvent(emitterToListenOn, emitterToEmitOn, event) {
emitterToListenOn.on(event, function() { //can't use arrow here, as we need 'arguments'
emitterToEmitOn.emit(event, arguments);
});
}
function forwardEvents(emitterToListenOn, emitterToEmitOn, events) {
events.forEach(event => forwardEvent(emitterToListenOn, emitterToEmitOn, event));
}
function forwardEventsToMultipleEmitters(emitterToListenOn, emittersToEmitOn, events) {
emittersToEmitOn.forEach(emitterToEmitOn => forwardEvents(emitterToListenOn, emitterToEmitOn, events));
}
对于那些不熟悉箭头功能的人,这里的代码相同,但没有:
function forwardEvent(emitterToListenOn, emitterToEmitOn, event) { emitterToListenOn.on(event, function() { //can't use arrow here, as we need 'arguments' emitterToEmitOn.emit(event, arguments); }); } function forwardEvents(emitterToListenOn, emitterToEmitOn, events) { events.forEach(function(event) { forwardEvent(emitterToListenOn, emitterToEmitOn, event); }); } function forwardEventsToMultipleEmitters(emitterToListenOn, emittersToEmitOn, events) { emittersToEmitOn.forEach(function(emitterToEmitOn) { forwardEvents(emitterToListenOn, emitterToEmitOn, events); }); }
要在原始代码中使用这些,
const EE = require('events');
const exportEvents = new EE();
const sumanEvents = Transform(); // create new transform stream (an event emitter)
forwardEvents(sumanEvents, exportEvents, ['test', 'error', 'suman-test-file-complete']);
这个forwardEvent
比jfriend00的forwardEmitter
更少的代码行,并没有覆盖任何函数,最终的解决方案看起来很干净。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.