是否可以等待 ofType 运算符中的所有操作被调用,然后再调用下一个?



我有一个 redux 操作数组,当调用 ALL 时,我想在我的史诗中调用另一个操作。数组中的操作是可变的、动态的。我希望找到的相当于像这样工作的ofType运算符:

ofType(FETCH_USER_PROFILE_SUCCESS && FETCH_USER_PREFERENCES_SUCCESS)

当两个操作都被调用时,将在管道的下游调用另一个操作。当然,ofType运算符不是这样工作的。它只需要调用其中一个操作即可继续。

我已经读到combineLatest可能是这里的解决方案,但我没有运气。以下是我想象的解决方案可能的样子,但显然这对我不起作用。任何建议将不胜感激。

const actions = ['FETCH_USER_PROFILE_SUCCESS', 'FETCH_USER_PREFERENCES_SUCCESS'];
const asTypes = actions.map((action) => ofType(action);
const userEpic = (action$, state$) =>
action$.pipe(
combineLatest(asTypes);
mergeMap(() =>
of({
type: 'SET_USER_READY'
})
)
);

以下是以下回复:

只是为了澄清我所说的动态是什么意思。操作数组可能包括更多操作,具体取决于用户的配置文件(例如"FETCH_USER_POSTS_SUCCESS"(,本质上是未知数量的操作,具体取决于用户。

因此,可以动态生成:

zip( action$.pipe(ofType('FETCH_USER_PROFILE_SUCCESS')), action$.pipe(ofType('FETCH_USER_PREFERENCES_SUCCESS')), )

const actions = ['FETCH_USER_PROFILE_SUCCESS', 'FETCH_USER_PREFERENCES_SUCCESS', unknown number of more actions];
const actions = dynamic.forEach((action) => action$.pipe(ofType(action))
zip(
actions
)

为什么不做一个像executeAllActions这样的常规操作,在这个动作有效负载中,你传递一个数组,其中包含你想要的所有动作的所有引用,比如

executeAllActions = {
type: 'exectueAllActions',
actionsList: [ fetchCategories, fetchProducts, ...],
}

然后你侦听这个动作

this.actions$.pipe(
ofType(executeAllActions),
concatMap(action => [ ...actions.actionsList ])
)

我们使用concatMap返回将全部执行的 actoins 列表。

我希望我现在能尝试这个想法,但我认为这在某种程度上是可能的。 如果它对您有用,请告诉我。

有很多方法可以解决这个问题,因为有一些重要的缺失细节。但我会做一些猜测:)

最大的问题是他们到达的顺序是否重要。如果没有,则使用zip()可能是您想要的。它将对排放量 1:1(实际上是任意数量的可观测值,而不仅仅是两个,例如 1:1:1 对三个,等等(

即使在这种情况下,也存在一个问题,即如果您收到操作的速率在它们之间有所不同,您想做什么。如果您收到FETCH_USER_PROFILE_SUCCESS的速度是收到FETCH_USER_PREFERENCES_SUCCESS的频率的两倍,会发生什么?你应该继续缓冲它们吗?你会放弃它们吗?你错了吗?

如果缓冲它们很好,或者您以其他方式保证它们将始终以相同的速率发生,zip()是有效的。


现在,如果你想确保它们按某种顺序出现,事情会变得更加复杂。你可能会有一个使用mergeMap,switchMap,exhaustMap或concatMap的链。决定哪个再次取决于你想做什么,如果你得到操作的速率并不总是相同的。

import { zip } from 'rxjs';
import { map, take, switchMap } from 'rxjs/operators';
import { ofType } from 'redux-observable';
// Pair up the emissions 1:1 but without regard to the sequence
// in which they are received i.e. they can be in either order
const userEpic = (action$, state$) =>
zip(
action$.pipe(ofType('FETCH_USER_PROFILE_SUCCESS')),
action$.pipe(ofType('FETCH_USER_PREFERENCES_SUCCESS')),
// ...etc more observables
).pipe(
map(() => ({
type: 'SET_USER_READY'
}))
);

// FETCH_USER_PROFILE_SUCCESS must come before FETCH_USER_PREFERENCES_SUCCESS
// and if we receive another FETCH_USER_PROFILE_SUCCESS before we get
// the FETCH_USER_PREFERENCES_SUCCESS, start over again (switchMap)
const userEpic = (action$, state$) =>
action$.pipe(
ofType('FETCH_USER_PROFILE_SUCCESS'),
switchMap(() =>
action$.pipe(
ofType('FETCH_USER_PREFERENCES_SUCCESS'),
take(1) // important! we only want to wait for one
)
),
map(() => ({
type: 'SET_USER_READY'
}))
)

数组中的操作是可变的、动态的

目前尚不清楚您希望它们如何更改,因此我没有包含这样做的机制。

--

这里还有一个类似的问题:https://stackoverflow.com/a/45554647/1770633

最新更新