目标是循环通过一个ID数组,并为每个ID进行一个API调用并调度一个带有结果的Action。
我目前的想法:
someEffect$ = createEffect(() => this.actions$.pipe(
ofType(someAction),
withLatestFrom(this.store.select(selectIds)),
switchMap(([_, ids]) => {
return forkJoin(ids.map(id =>
this.service.getData(id))).pipe(
map(result => {
return actionSuccess({result});
}),
catchError((error: HttpErrorResponse) => {
return of(actionError({error}));
})
)
})
));
这有点奏效,但有两种不想要的行为:
- actionSuccess只被调度一次,并且所有api调用的结果都是一个数组。我想要每个API调用一个分派
用merge替换forkJoin会触发每个ID的操作,但随后API调用不再发生,因此必须有更多的调用。
- forkJoin等待所有API调用完成,然后继续。我想在每次getData((完成后立即调度actionSuccess
我知道你在问如何调度在effects
中的数组中循环的操作,但如果让组件处理循环操作,你会为每个id调度一个成功的操作,那又如何呢。
组件:
loadCustomerById(): void {
this.store.select(ClientSelectors.selectIds).subscribe((ids) => {
if (ids.length) {
for (const id of ids) {
this.store.dispatch(ClientActions.loadCustomerById({ payload: id }));
}
}
})
}
效果:
loadCustomerById$ = createEffect(() => this.actions$.pipe(
ofType(loadCustomerById),
// you already get the id from action
// no need of withLastestFrom
mergeMap(({ payload: id }) =>
this.service.getData(id).pipe(
map((response) => ClientActions.loadCustomerByIdSuccess({ payload: response })),
catchError((error) => of(ClientActions.loadCustomerByIdFail({ error })))
)
)
));
使用merge而不是forkJoin-有关更多信息,请参阅https://timdeschryver.dev/snippets#multiple-来自有效的服务调用
refresh$ = createEffect(() =>
this.actions$.pipe(
ofType(CustomerActions.refresh),
exhaustMap(({ customerIds }) =>
merge(
...ids.map((id) =>
this.customersService.getCustomer(id).pipe(
map(CustomerActions.getCustomerSuccess),
catchError((err) =>
of(CustomerActions.getCustomerFailed(id, err.message)),
),
),
),
),
),
),
)
我建议将数组的Observable转换为Observable,该Observable使用from
:发射数组中的所有元素
someEffect$ = createEffect(() => this.actions$.pipe(
ofType(someAction),
withLatestFrom(this.store.select(selectIds)),
switchMap(([_, ids]) => from(ids)),
mergeMap(id => this.service.getData(id).pipe(
map(result => actionSuccess({ result })),
catchError(error => of(actionError({ error })))
))
));
然而,根据ids
的长度,这可能很快变得无法维持,并且可能值得重构后端以接受批处理调用。