【问题标题】:Why isn't this EventEmitter pubsub singleton interface working in node.js?为什么这个 EventEmitter pubsub 单例接口在 node.js 中不起作用?
【发布时间】:2019-04-15 10:03:12
【问题描述】:

我试图在 node.js 中分离发布者和订阅者,以便能够通过共享的 EventEmitter 实例作为总线相互发送数据。

我的巴士遵循讨论过的单例方法 [这里][1]

bus.js 文件

// https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/
// create a unique, global symbol name
// -----------------------------------

const FOO_KEY = Symbol.for("test.exchanges.bus");
const EventEmitter = require("events");

// check if the global object has this symbol
// add it if it does not have the symbol, yet
// ------------------------------------------

var globalSymbols = Object.getOwnPropertySymbols(global);
var hasFoo = (globalSymbols.indexOf(FOO_KEY) > -1);

if (!hasFoo){
  global[FOO_KEY] = {
    foo: new EventEmitter()
  };
}

// define the singleton API
// ------------------------

var singleton = {};

Object.defineProperty(singleton, "instance", {
  get: function(){
    return global[FOO_KEY];
  }
});

// ensure the API is never changed
// -------------------------------

Object.freeze(singleton);

// export the singleton API only
// -----------------------------

module.exports = singleton;

我的理解是,当我在不同的模块中需要这个文件时,应该使相同的 foo 对象可用。这不就是单例的目的吗?

pub.js 文件

const bus = require("./bus");

class Publisher {
    constructor(emitter) {
        this.emitter = emitter;
        console.log(this.emitter);
        this.test();
    }

    test() {
        setInterval(() => {
            this.emitter.emit("test", Date.now());
        }, 1000);
    }

}

module.exports = Publisher;

console.log(bus.instance.foo);

sub.js 文件

const bus = require("./bus");

class Subscriber {
    constructor(emitter) {
        this.emitter = emitter;
        console.log(this.emitter);

        this.emitter.on("test", this.handleTest);
    }

    handleTest(data) {
        console.log("handling test", data);
    }
}

module.exports = Subscriber;

console.log(bus.instance.foo);

当我在 2 个单独的终端窗口上运行 pub.js 和 sub.js 时,sub.js 立即完成执行,就好像发布者没有将消息推送给它一样。谁能指出如何将发布者和订阅者分开以使用相同的事件总线?

【问题讨论】:

    标签: node.js singleton publish-subscribe eventemitter


    【解决方案1】:

    您可以考虑重新设计您的总线模块。我建议将其创建为扩展 EventEmitter 的类,然后返回该类的实例化实例。

    现在当第一次加载这个文件时,类代码将运行,一个对象将被实例化然后导出回来。 require 将缓存此实例,下次加载此文件时,它将返回相同的对象。这使它成为单例,您现在可以将其用作公共总线。

    这里有一些代码来证明这一点:

    bus.js

    const {EventEmitter} = require('events');
    class Bus extends EventEmitter {
      constructor(){
        super();
        setTimeout(() => this.emit('foo', (new Date()).getTime()), 1000);
      }
    }
    module.exports = new Bus();
    

    bus.spec.js

    const bus1 = require('../src/util/bus');
    const bus2 = require('../src/util/bus');
    
    describe('bus', () => {
      it('is the same object', () => {
        expect(bus1).toEqual(bus2);
        expect(bus1 === bus2).toEqual(true);
      });
      
      it('calls the event handler on bus2 when event is emitted on bus1', done => {
        bus2.on('chocolate', flavor => {
          expect(flavor).toBe('dark');
          done()
        });
        bus1.emit('chocolate', 'dark');
      }, 20)
    });
    

    【讨论】:

      猜你喜欢
      • 2012-08-17
      • 2015-02-23
      • 1970-01-01
      • 2017-11-25
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      相关资源
      最近更新 更多