Redux Observableでアクションのシーケンスを待機する質問する

Redux Observableでアクションのシーケンスを待機する質問する

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

本質的には、次のようなことをしたいのです。

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

FETCH_ERRORたとえば、別のタイプのアクションが起動された場合は、そのシーケンスをキャンセルして最初からやり直したいと思います。

ベストアンサー1

素晴らしい質問です。重要な点は、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単一の をリッスンする内部 Observable チェーンのリッスンを開始しますFETCH_SUCCESS。これが重要なのは、.take(1)そうしないと、複数の をリッスンし続けることになりFETCH_SUCCESS、奇妙なバグが発生する可能性があるためです。また、そうでなくても、必要なものだけを取得するのが一般的にベストプラクティスです。

先に受信した場合、takeUntil待機をキャンセルするために使用します。FETCH_SUCCESSFETCH_ERROR


ボーナスとして、エラーに基づいて分析も​​行いたい場合は、最初からやり直すだけでなく、 をrace2 つのストリーム間で実際に競合させるために使用できます。最初に送信したものが勝ち、もう一方はサブスクライブ解除されます。

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)
  );

おすすめ記事