Async: 非同期を使用したイベントハンドラーの設定

作成日 2016年10月25日  ·  4コメント  ·  ソース: caolan/async

イベントハンドラーを含む統合テストの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番目の部分としてチェックを実行します。 ただし、タスクを順番に開始するために技術的に並行する必要はありません(おそらくそうなるでしょうが)。 また、特により複雑なセットアップでは、コードのフラットさが低下します。

question

最も参考になるコメント

ちなみに、これは私が見た中で最もクレイジーな自動ユースケースだと思います:building_construction:

全てのコメント4件

こんにちは@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`
});

基本的に、 eventcheckResults依存関係を交換するだけですが、 eventcheckResultsハンドラーに依存するため、実際には少しクリーンになる可能性があります。 checkResultsは、ハンドラーをevent渡すだけです。

実行順序は次のようになります。
checkResults --> event --> emit --> handler (passed to event from checkResults) --> checkEmit --> done

不明な点があれば教えてください。

ええ、それは問題を解決します。 ありがとう!

ちなみに、これは私が見た中で最もクレイジーな自動ユースケースだと思います:building_construction:

同意しました。 通常、非同期コールバックとイベントエミッターはうまく混ざりません...

このページは役に立ちましたか?
0 / 5 - 0 評価