次のコードがあります。基本的に EventEmitter を拡張して、イベントを発行して忘れるのではなく、実際に結果を収集します。
これに対する答えとして書きました: EventEmitter implementation that allows you to get the listener's results?
このコードの問題は、すべてのリスナーが非同期であると想定していることです。それらの 1 つが非同期の場合、async.series は単純に失敗します。
私の考えは、最後のパラメーターが関数であるかどうかをチェックする関数でリスナーをラップすることです。そうではなく、非同期呼び出しと同様の方法で機能する関数でラップする必要があります。しかし、私はこれをやって惨めに失敗しています。
ヘルプ?
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 );
}
これをテストする簡単な方法は次のとおりです。
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 );
});
ありがとう!