propagate icon indicating copy to clipboard operation
propagate copied to clipboard

listenersCount & newListener event

Open xamgore opened this issue 5 years ago • 1 comments

Hi! Node.js v0.1.26 implemented a special event newListener. It is emitted once any new listener is added to an EventEmitter. It seems to me that dest.on(...) should trigger source to emit newListener event. In the example below the code prints nothing:

const ee1 = new EventEmitter()
const ee2 = new EventEmitter()

ee1.once('newListener', (event, listener) => console.log('ee1 new listener'))
ee2.once('newListener', (event, listener) => console.log('ee2 new listener'))

propagate(ee1, ee2)

// should print:
// ee1 new listener
// ee2 new listener
ee2.on('event', (a, b) => console.log('got propagated event', a, b))

I faced the issue while propagating MongoDB change streams into Node's EventEmitter. As you can see in the code, ChangeStream extends EventEmitter and calls emit method only if newListener was fired. In other words, there must be at least one event listener registered. listenerCount also has to be changed.

this.on('newListener', eventName => {
  if (eventName === 'change' && this.cursor && this.listenerCount('change') === 0) {
    this.cursor.on('data', change => processNewChange(this, change));
  }
});

What do you think about it?

xamgore avatar May 26 '20 19:05 xamgore

@xamgore As an alternative, you could use EventEmitter2 emitter as a relay. Every instance of the EventEmitter2 class has the listenTo method to do the similar things, but instead of replacing the emit method on the source it just subscribe to the events you need and emits them through itself. All the listeners will be append to the source emitter on demand, so this should work.

const EventEmitter= require('events').EventEmitter;
const EventEmitter2= require('eventemitter2');

const source= new EventEmitter();

const dest= new EventEmitter2({
    newListener: true,
    removeListener: true
});

source.once('newListener', (event, listener) => console.log('ee1 new listener'))

dest.once('newListener', (event, listener) => console.log('ee2 new listener'))

dest.listenTo(source, 'event');

console.log('listening...');

dest.on('event', (...data)=> console.log('emitted', data)); //append listener to the source on demand

source.emit('event', 1, 2, 3);

Console output:

ee2 new listener
listening...
ee1 new listener
emitted [ 1, 2, 3 ]

Process finished with exit code 0

DigitalBrainJS avatar Jun 03 '20 15:06 DigitalBrainJS