很好的问题。重要的一点是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,这可能会导致奇怪的错误,即使不是,通常也是最好的做法,只取你需要的东西。
如果我们先收到FETCH_ERROR,我们使用takeUntil 取消等待FETCH_SUCCESS。
作为奖励,如果您决定也要根据错误进行一些分析,不仅要重新开始,您还可以使用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)
);