イベントハンドラーを含む統合テストの1つで非同期を使用するのに問題があります。 問題は、イベントが発行される前に、イベントハンドラーを(非同期で提供されるコールバックを参照して)セットアップする必要があることです。 ただし、イベントハンドラコードには、すぐに追加のコールバックが必要です。
問題を示す簡単な例を次に示します。
async.auto({
// This needs to run first, but it will finish second
event: [(next) => {
emitter.once('awesome', next);
}],
// This needs to finish near the end
checkResults: ['event', (results, next) => {
assert(results.event.status == 200);
assert(results.event.msg == 'cool');
// Do other async stuff...
somethingAsync(next);
}],
// This has to start second, but before the first one finishes
emit: ['event', (results, next) => {
event.emit('awesome', {msg: 'cool'}, next);
}],
checkEmit: ['emit', (results, next) => {
// some sort of check that can be async
},
], done);
event
を最初に開始する必要がありますが、 emit
が発生するまで終了しません。 emit
は、 event
が開始するのを待つ必要がありますが、終了する必要はありません(別名、ハンドラーを設定するだけです)。 したがって、これは終了しません。
現在の非同期ライブラリでこれを行う方法はありますか? (きれいに)
これが非同期で実装できると仮定して、私が望む解決策はここにあります
async.auto({
listen: [(next, done) => {
client.on(done);
return next();
},
...
}, callback);
タスクの配列として、エミッターとリスナー(テストでは複数存在する可能性があります)を実行する並列を使用できます。 結果を取得し、2番目の部分としてチェックを実行します。 ただし、タスクを順番に開始するために技術的に並行する必要はありません(おそらくそうなるでしょうが)。 また、特により複雑なセットアップでは、コードのフラットさが低下します。
こんにちは@Saevon 、質問ありがとう
それを行うための迅速でクリーンな方法は次のとおりです。
async.auto({
// This needs to finish near the end
checkResults: [(next) => {
return next(null, (results, next) => {
assert(results.event.status == 200);
assert(results.event.msg == 'cool');
// Do other async stuff...
// somethingAsync(next);
});
}],
// This needs to run first, but it will finish second
event: ['checkResults', (handler, next) => {
emitter.once('awesome', handler.checkResults);
return next();
}],
// This has to start second, but before the first one finishes
emit: ['event', (results, next) => {
// Should this be emitter.emit instead of event.emit?
event.emit('awesome', {msg: 'cool'}, next);
}],
checkEmit: ['emit', (results, next) => {
// the results of `checkResults` will be in `results.emit`
// as the handler on 'awesome' was passed the `next`
// callback from `emit`
// some sort of check that can be async
yourChecks(next);
}]
}, function done(err) {
// everything finished running, unless `err` !== `null`
});
基本的に、 event
とcheckResults
依存関係を交換するだけですが、 event
はcheckResults
ハンドラーに依存するため、実際には少しクリーンになる可能性があります。 checkResults
は、ハンドラーをevent
渡すだけです。
実行順序は次のようになります。
checkResults --> event --> emit --> handler (passed to event from checkResults) --> checkEmit --> done
。
不明な点があれば教えてください。
ええ、それは問題を解決します。 ありがとう!
ちなみに、これは私が見た中で最もクレイジーな自動ユースケースだと思います:building_construction:
同意しました。 通常、非同期コールバックとイベントエミッターはうまく混ざりません...
最も参考になるコメント
ちなみに、これは私が見た中で最もクレイジーな自動ユースケースだと思います:building_construction: