web-dev-qa-db-ja.com

Redux Observableで一連のアクションを待つ

Redux Observableを使用して別のアクションをディスパッチする前に、アクションのシーケンスを待つ必要がある使用例があります。私はいくつかの同様の質問を見てきましたが、私の特定のユースケースでこれらのアプローチをどのように使用できるかを理解することはできません。

本質的に私はそのようなことをしたいです:

action$
  .ofType(PAGINATION_CLICKED) // This action occurred.
  .ofType(FETCH_SUCCESS) // Then this action occurred after.
  .map(() => analyticsAction()); // Dispatch analytics.

タイプFETCH_ERRORの別のアクションが発生した場合などは、そのシーケンスをキャンセルしてやり直したいと思います。

17
Matt Derrick

すばらしい質問です。重要な点は、_action$_がディスパッチされたときのすべてのアクションのホット/マルチキャストストリームであることです(サブジェクトです)。暑いので、何度も組み合わせることができ、すべて同じアクションの流れを聞いています。

_// uses switchMap so if another PAGINATION_CLICKED comes in
// before FETCH_SUCCESS we start over

action$
  .ofType(PAGINATION_CLICKED)
  .switchMap(() =>
    action$.ofType(FETCH_SUCCESS)
      .take(1) // <-------------------- very important!
      .map(() => analyticsAction())
      .takeUntil(action$.ofType(FETCH_ERROR))
  );
_

したがって、_PAGINATION_CLICKED_を受け取るたびに、単一の_FETCH_SUCCESS_をリッスンする内部の監視可能チェーンのリッスンを開始します。 .take(1)があることが重要です。そうしないと、複数の_FETCH_SUCCESS_をリッスンし続けるため、奇妙なバグが発生する可能性があります。

最初に_FETCH_SUCCESS_を受け取った場合、takeUntilを使用して_FETCH_ERROR_の待機をキャンセルします。


おまけとして、最初からやり直すだけでなく、エラーにも基づいていくつかの分析処理も実行したい場合は、raceを使用して2つのストリーム間で実際に競合することができます。最初に放出するものが勝つ。もう1つはサブスクライブされていません。

_action$
  .ofType(PAGINATION_CLICKED)
  .switchMap(() =>
    Observable.race(
      action$.ofType(FETCH_SUCCESS)
        .take(1)
        .map(() => analyticsAction()),
      action$.ofType(FETCH_ERROR)
        .take(1)
        .map(() => someOtherAnalyticsAction())
    )
  );
_

以下は同じですが、静的演算子の代わりにraceをインスタンス演算子として使用しています。これは、選択できるスタイル設定です。どちらも同じことをします。どちらかわかりやすい方を使用してください。

_action$
  .ofType(PAGINATION_CLICKED)
  .switchMap(() =>
    action$.ofType(FETCH_SUCCESS)
      .map(() => analyticsAction())
      .race(
        action$.ofType(FETCH_ERROR)
          .map(() => someOtherAnalyticsAction())
      )
      .take(1)
  );
_
26
jayphelps