12

私はNodeJSでExpressを使用してアプリケーションを作成し、EventEmitterを使用して、発行されたイベントをリッスンすることでプラグインがメインコードにフックする一種のプラグインアーキテクチャを作成しようとしています。

私の問題は、プラグイン関数が非同期リクエストを行うときに発生します(この場合は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個または多数ある可能性があるためです。理想的には、メインアプリに制御を戻す前に、DBのものが終了するのを待つ方法が必要です。

どうもありがとう

4

5 に答える 5

5

プラグイン/ミドルウェア管理に EventEmitter を使用することは理想的ではありません。リスナーに非同期コードがある場合、リスナーが順次実行されることを保証できないからです。これは特に、これらのリスナーが相互に、または同じデータと対話する場合に問題になります。

これが、Connect/Express ミドルウェア関数が配列に格納され、EventEmitter を使用する代わりに次々に実行される理由です。それぞれ next(); を呼び出す必要があります。タスクを完了したときに機能します。

于 2012-04-07T09:21:09.653 に答える
4

非同期呼び出しと同期動作を混在させることはできません。イベントエミッターに固執する場合(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
  }
});
于 2012-04-09T17:17:09.960 に答える
3

クライアントに応答を返す前に待機する必要があるイベントと、そうでない場合がある (HTTP 要求コンテキストでない場合) いくつかのイベントについて、同じような決定を下す必要がありました。

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

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

イベントで、コールバックがあるかどうかを確認します。

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

イベントとコールバックを混在させると面倒になる可能性があることはわかっていますが、必要なものには問題なく機能します。私が見るもう1つの解決策は、@redbenによって提案されたものです。イベントの最後に発行機能を追加します。HTTP コンテキストでの問題は、一意のキーが必要であるため、ユーザーごとに異なる処理を行う場合にイベントが台無しにならないようにすることです。

于 2014-01-20T09:58:16.360 に答える