![](/img/trans.png)
[英]RxJS / Angular 2 / @ngrx/store /effects how to combine actions
[英]NGRX Effects / RXJS: Loop API Calls and Actions
目标是循环遍历 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}));
})
)
})
));
这有点管用,但有两种不良行为:
将 forkJoin 替换为 merge 会触发每个 ID 的操作,但随后 API 调用不再发生,因此必须有更多。
我知道你在问如何在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-service-calls-from-an-effect
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)),
),
),
),
),
),
),
)
我建议将 Array 的 Observable 转换为 Observable,它使用from
发出 Array 中的所有元素:
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
的长度,这可能很快变得站不住脚,并且可能值得重构您的后端以接受批处理调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.