我是RxJS的新手,对不起,如果抱歉。
假设我想拥有一个可重用的史诗来获取用户,该用户将通过应用加载史诗中的操作来调用。
过度简化的示例:
const getUserEpic = action$ =>
action$.pipe(
ofType(GET_USER_REQUEST),
switchMap(action => from(service.fetchUser(action.userId).pipe(
mapTo({ type: GET_USER_SUCCESS })))
),
);
const appLoadEpic = action$ =>
action$.pipe(
ofType(LOAD_APP_REQUEST),
map(() => of({ type: GET_USER_REQUEST }, { type: SOME_OTHER_REQUEST }))
);
如果我想在所有调用的史诗(getUser等)完成后再调用LOAD_APP_SUCCESS
,该怎么办?如果可以在appLoadEpic中完成,那就太好了,但恐怕是不可能的。
答案 0 :(得分:2)
我建议这样做的方式是将各个史诗组合成一个“元”史诗。也就是说,您可以使用各个流来侦听其各个事件,并在所有合并的流完成后传播它们。
const getUserEpic = action$ => ...
const someOtherEpic = action$ => ...
// Creates an epic that merges all the results from each provided epic
const initializationEpic = combineEpics(getUserEpic, someOtherEpic)
const appLoadEpic = (action$, state$) => {
// Runs the new epic with the action and state values.
const onLoad$ = initializationEpic(action$, state$).pipe(
endWith({type: LOAD_APP_SUCCESS})
)
// Listen for the load app request before subscribing to the initialization
action$.pipe(
ofType(LOAD_APP_REQUEST),
mergeMapTo(onLoad$),
)
}
如果您感觉花哨并且不想通过导入注入史诗,则还可以动态注入史诗docs详细介绍了一种异步注入史诗的方法,这意味着您可以进行文件注入可以在启动过程中将其作为动作主体的一部分包含在内,这可能会使测试更加容易。
const appLoadEpic = (action$, state$) => {
// Listen for the load app request before subscribing to the initialization
action$.pipe(
ofType(LOAD_APP_REQUEST),
// Now the epic is injected during the app loading, and you run it inline
// here. This makes it easy to mock it during testing
mergeMap(({epic}) => epic(action$, state$).pipe(endWith({type: LOAD_APP_SUCCESS}))),
)
}