2012-04-07 15 views
5

ExpressとNodeJSで書かれたアプリケーションを持っていて、EventEmitterを使って、プラグインを使ってプラグインを作成しようとしました。NodeJSがイベント発生時にコールバックを終了する

私の問題は、非同期要求(この場合はmongoからデータを取得する)を行うとプラグインコードが終了し、制御が元のエミッタに戻り、非同期要求プラグインのコードが終了します。

例:

主なアプリケーション:

// We want to modify the request object in the plugin 
self.emit('plugin-listener', request); 

プラグイン:

// Plugin function listening to 'plugin-listener', 'request' is an arg 
console.log(request); 

// Call to DB (async) 
this.getFromMongo(some_data, function(response){ 
    // this may not get called until the plugin function has finished! 
} 

'getFromMongo' 関数から戻ってメインのコードにコールバック関数を避けるための私の理由はそれがありますイベントをリッスンしている0または多くのプラグインかもしれません。理想的には私はあなたがリスナーがあることを保証することはできませんので、メインのアプリにプラグイン/ミドルウェア管理のために持つEventEmitterを使用して

多くのおかげ

答えて

3

を制御を返す前に終了するDBのものを待つためにいくつかの方法は、理想的ではありませんしたいですそれらが非同期コードを有する場合、順次実行される。これは特に、これらのリスナーがお互いや同じデータとやり取りするときに問題になります。

なぜなら、ミドルウェア関数の接続/表現は、EventEmitterを使用する代わりに配列に格納され、順番に実行されるからです。彼らはそれぞれnext()を呼び出す必要があります。彼らは彼らの仕事をやっているときに機能します。

3

非同期呼び出しと同期動作を混在させることはできません。イベントエミッター(Klovadisが指摘しているようにあなたには理想的ではないかもしれません)に固執する場合は、プラグインが主なアプリケーションの機能をトリガーするイベントを発生させる必要があります実行するために「待つ」。また、すべてのプラグイン呼び出しがMongoDBコールバックを終了するまでメインコードが実行されないように、イベント呼び出しを待っているすべてのプラグイン呼び出しを追跡する必要があります。

var callList = ['pluginArgs1', 'pluginArgs2', 'pluginArgs3']; 
for (var i = 0; i < callList.length; i++){ 
    self.emit('plugin-listener', callList[i], i); 
} 

self.on('plugin-callback', function(i){ 
    callList.splice(i, 1); 
    if (callList.length < 1){ 
    //we're done, do something 
    } 
}); 
0

はそれを自分自身を試していないが、あなたはイベント放出されるコードで実行するための関数の配列としてイベントのデータオブジェクトのプロパティを使用することができ :

リスナーを

foo.on('your-event', function(data) { 
    console.log(data); 
    // Then add the asynchronous code to a callbacks array 
    // in the event data object 
    data.callbacks.push(function(next) { 
    getFromMongo(some_data, function(err, result) { next(err) } 
    } 
}); 

エミッタ

self.emit('your-event', data); 
// listeners have modified data object, 
// some might have added callback to data.callbacks 
// (suppose you use async) 
async.series(data.callbacks); 
1

は、いくつかのイベントについて作るために意思決定の同じ種類を持っていたことクライアントへの応答を返す前に待機する必要があり、HTTP要求コンテキストにないときに応答しないこともあります。

最も簡単な方法は、イベントの最後の引数としてコールバックを追加することでした。私は必要なもののために

Stuff.on('do_some_stuff', function(data, data2, callback) { 
    // stuff to do 
    // ... 
    if (typeof callback === "function") return callback(err, result); 
}); 

私はミキシングイベントとコールバックが乱雑することができることを知っているが、その作業罰金:イベントチェックで

Stuff.emit('do_some_stuff', data, data2, callback); 

は、コールバックがある場合。 私が見る他の解決策は、@redbenによって提案されたものです:イベントの最後にemit関数を追加してください。 HTTPコンテキストでの問題は、ユーザーごとに異なる処理を行う場合にイベントが混乱しないように、固有のキーが必要なことです。

関連する問題