I have the following code. It basically extends EventEmitter so that rather than emitting the event and forget about it, it actually collects the results.
I wrote it as an answer to this: EventEmitter implementation that allows you to get the listeners' results?
The problem with this code is that it assumes that every listener is asynchronous. If one of them is asynchronous, then async.series simply fails.
My idea is to wrap the listener with a function that checks if its last parameter is a function. It it's not, it should wrap it with a function that works in a similar fashion as async calls. But, I am failing miserably ad doing this.
Help?
var events = require('events');
var util = require('util');
var async = require('async');
// Create the enhanced EventEmitter
function AsyncEvents() {
events.EventEmitter.call(this);
}
util.inherits(AsyncEvents, events.EventEmitter);
// Just a stub
AsyncEvents.prototype.onAsync = function( event, listener ){
return this.on( event, listener );
}
// Async emit
AsyncEvents.prototype.emitAsync = function( ){
var event,
module,
results = [],
functionList = [],
args,
callback,
eventArguments;
// Turn `arguments` into a proper array
args = Array.prototype.splice.call(arguments, 0);
// get the `hook` and `hookArgument` variables
event = args.splice(0,1)[0]; // The first parameter, always the hook's name
eventArguments = args; // The leftovers, the hook's parameters
// If the last parameter is a function, it's assumed
// to be the callback
if( typeof( eventArguments[ eventArguments.length-1 ] ) === 'function' ){
callback = eventArguments.pop(); // The last parameter, always the callback
}
var listeners = this.listeners( event );
listeners.forEach( function( listener ) {
// Pushes the async function to functionList. Note that the arguments passed to invokeAll are
// bound to the function's scope
functionList.push( function( done ){
listener.apply( this, Array.prototype.concat( eventArguments, done ) );
} );
});
callback ? async.series( functionList, callback ) : async.series( functionList );
}
Here is an easy way to test it:
asyncEvents = new AsyncEvents();
asyncEvents.onAsync('one', function( paramOne1, done ){
done( null, paramOne1 + ' --- ONE done, 1' );
});
asyncEvents.onAsync('one', function( paramOne2, done ){
done( null, paramOne2 + ' --- ONE done, 2' );
});
// Uncomment this and async will fail
//asyncEvents.onAsync('one', function( paramOne3, done ){
// return paramOne3 + ' --- ONE done, 3' ;
//});
asyncEvents.onAsync('two', function( paramTwo, done ){
done( null, 'TWO done, 1' );
});
asyncEvents.emitAsync('one', 'P1', function( err, res ){
console.log( err );
console.log( res );
});
asyncEvents.emitAsync('two', 'P2', function( err, res ){
console.log( err );
console.log( res );
});
Thanks!