2

I realise that nodejs has a powerful EventEmitter constructor which allows you to emit events. However, what EventEmitter is missing is a way for the event emitter to see what the listeners returned.

This is the functionality I am after:

e = new FantasticEventEmitter();

e.on( 'event1', function( param1, param2, cb ){
  console.log("First listener called...")
  cb( null, 10 );
});

e.on( 'event1', function( param2, param2, cb ){
   console.log("Ah, another listener called!");
   cb( null, 20 );
});

e.emit( 'event1', 'firstParameter', 'secondParameter', function( err, res ){
  console.log("Event emitted, now res will be [ 10, 20]");
});

Basically, I want listeners to be able to register, getting called when an event is fired up, and:

  • Listeners to be passed a callback parameter. the callback will "collect" the results
  • Emitters to have a callback, which will get called with the result collections

Is there a library that does this already, before I reinvent the wheel?

Merc
  • 16,277
  • 18
  • 79
  • 122
  • Even after posting this question, I looked and looked and yet... no, I couldn't find a ready-made library for this. I think the best way to go about it is to inherit from EventEmitter and rewrite `emit()` so that it calls `allListeners` with `async` after adding the callback to its argument. It's quite trivial to do this, but... nobody has ever done it? Nor ever needed it? Really? – Merc Oct 07 '13 at 03:13

3 Answers3

1

There is no easy way to do it. To allow what I asked for, I wrote this GutHub module:

EventEmitterCollector.

Enjoy...

Merc
  • 16,277
  • 18
  • 79
  • 122
0

Correct me if I am wrong but I don't think it should be. Event Emitter should not return callback results. Eventemiiters are an alternative to asynchronous function calls, if you use them correctly. You should not try to combine them and complicate stuff.

If you use them properly you can do what you want without async. There is no generalized way with eventemitter. Here is how I would do it :

  • Event incoming : process the parameters and trigger stepn in any fashion.
  • Event stepn : different for each step, do each step and at end call collect or call another intermediate step.
  • Event collect : store the outputs check for completion and call done when finished.
  • Event done : final callback (can be done in the collect itself).

This is totally my opinion/what i learned : asynchronous callbacks are the end result of internally evented execution. If you were to implement a async job at low-level, this is how you would do it. At high level with function callbacks and stuff, you would use async.

user568109
  • 47,225
  • 17
  • 99
  • 123
  • I fail to see how doing something by hand would be beneficial, rather than having a simple, straight-forward way of seeing what the listeners return in an async fashion... – Merc Oct 07 '13 at 15:16
  • It would be simple from POV of ease of use, not ease of implementation. Think like a developer, not a user. Asynchronous callbacks are an abstraction built on underlying synchronous operations. – user568109 Oct 07 '13 at 15:25
  • Err... I am thinking like a developer who likes staying sane, I think. Please see my own answer... – Merc Oct 29 '13 at 08:05
-1

Maybe I'm misinterpreting your question, but your desired result code from your original question should just work. You can pass in a callback function as a parameter. EventEmitter instances you define can take callback arguments already. I made an example that shows how to do what you wanted with little change to your original.

var EventEmitter = require('events').EventEmitter;

var e = new EventEmitter();

// first listener
e.on('whatever', function(x,cb) {
    console.log('first listener');
    cb(10);
});

// second listener
e.on('whatever', function(x,cb) {
    console.log('second listener');
    cb(20);
});

// emit logic
var res = [];
e.emit('whatever', 'parameter', function(val) {
    res.push(val);
});
console.log('Event emitted, now res will be [' + res.join(',') + ']');