NGRX效果/RXJS:Loop API调用和操作



目标是循环通过一个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}));
})
)
})
));

这有点奏效,但有两种不想要的行为:

  1. actionSuccess只被调度一次,并且所有api调用的结果都是一个数组。我想要每个API调用一个分派

用merge替换forkJoin会触发每个ID的操作,但随后API调用不再发生,因此必须有更多的调用。

  1. 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的长度,这可能很快变得无法维持,并且可能值得重构后端以接受批处理调用。

相关内容

  • 没有找到相关文章

最新更新