等待Redux Observable中的一系列操作序列

22

我有一个使用场景,在Redux Observables中需要等待一系列操作完成后才能发起另一个操作。我看到了一些类似的问题,但是我无法理解如何将这些方法用于我的特定情况。

本质上,我想要做的事情如下:

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

如果出现另一种类型为FETCH_ERROR的操作,我也想取消并重新开始该序列。

1个回答

34

很好的问题。重要的是,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_SUCCESS”的过程,如果我们先收到了“FETCH_ERROR”。
作为额外的奖励,如果您决定基于错误信息进行一些分析,并非仅仅是重新开始,您可以使用“race”来在两个流之间进行竞争。先发出信号的那个获胜,另一个则被取消订阅。
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)
  );

我差不多到达了目标!最终我使用了你的第一个示例,但没有加上(现在显然很关键的)take(1)。这基本上意味着在第一个“PAGINATION_CLICKED”之后,“序列”被忽略了。非常感谢,对于该库提供了很好的支持 :) - Matt Derrick
有没有一种方法可以指示在产生第三个动作之前,我希望两个动作都被调用/完成,而不是竞争? - Nick
编辑:算了,我觉得我用 zip 操作符解决了这个问题。 - Nick
改变生活的技巧! - tszarzynski
在你的第一个代码示例中,使用exhaustMap而不是switchMap会更好吗?如果方法analyticsAction()需要一些时间,并且在此期间我们收到pagination_clicked动作,则它将取消方法analyticsAction()。 - John
@John 或许吧。这完全取决于一个人想要的行为。你甚至可能想要使用 mergeMap。这都由你决定。 - jayphelps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接