0

I'd like for an object B to subscribe to the events than an object A emits—however, I don't want to pass the object B itself to A, because of the potential for another developer (or myself in the future) to abuse presence of B in A, and thus tightly couple the two items. Is there a way I can pass only the event-emitter aspect of B to A, so that A can receive events from (i.e. read) B, but not manipulate (i.e. write to) B?

A somewhat simple solution I can think of would be to create a new EventEmitter C, then subscribe C to all events of B, with handlers that emit the same events, and then pass C to A.

Is there a simpler solution?

xyz
  • 1,513
  • 2
  • 13
  • 17

1 Answers1

0

The usual term for what you're asking for is a proxy.

You create a new object. Give it only the methods that you want to expose. In a private closure, you have the actual eventEmitter object and the few methods you want to expose can just operate on the actual eventEmitter object, but nobody with access to only the proxy can modify the actual eventEmitter object or use any methods on the emitter that you didn't explicitly expose in the proxy. Here's a simple example that just lets the .on() method be used through the proxy (no other methods on the emitter can be called).

class EmitterProxy {
    constructor(emitter) {
        // add method that has access to emitter
        this.on = function(event, fn) {
            let self = this;
            return emitter.on(event, function() {
                // this makes sure that the value of this is the EmitterProxy
                // instance and not the emitter instance
                fn.apply(self, arguments);
            });
        }

        // define any other methods you want to proxy
    }
}

Then, in your code, you create the proxy and pass it the actual eventEmitter. You can then share the proxy object with anyone you want. They can listen for events on it, but they can't do anything else to the emitter itself.

let proxy = new EmitterProxy(actualEmitter);

Then pass proxy to other code where it only has access to the one method.

// other code can do this
proxy.on('finish', () => { /* do something here */ });
jfriend00
  • 683,504
  • 96
  • 985
  • 979