繁体   English   中英

将事件从一个事件发射器转发到另一个事件发射器

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM