我需要在调用 API 请求后分派多个操作。 我目前正在使用此代码在 API 请求完成后分派一个操作:
changeStatus$ = createEffect(() =>
this.actions$.pipe(
ofType(fromJtDetail.changeStatus),
switchMap(action =>
this.jtDetailService.changeStatus(action.entity,action.jobTicketId).pipe(
map(res => fromJtDetail.statusChanged({changedStatus: action.entity.newStatus})),
catchError(error => EMPTY)
))));
在此效果中调度更多动作非常重要,无法为此编写其他效果。
您可以使用
switchMap
+ of(
分派多个操作
changeStatus$ = createEffect(() =>
this.actions$.pipe(
ofType(fromJtDetail.changeStatus),
switchMap(action =>
this.jtDetailService.changeStatus(action.entity,action.jobTicketId).pipe(
switchMap(res => of(
fromJtDetail.statusChanged({changedStatus: action.entity.newStatus}),
fromHere.doSmthAction(), // <-- additional action 1
fromThere.doSmthElseAction(), // <-- additional action 2
)),
catchError(error => EMPTY)
))));
编辑:
虽然可以做,但你不应该这样做。
看一下
无多重操作效果
这里的所有答案都是正确的,“简单”的答案和解决方案是返回一组操作。然而,这是一种不好的做法,有关更多信息,请参阅 NgRx ESLint 文档中的No Multiple Actions In Effects。
您可以将操作数组传递到 switchMap 中,如下所示:
switchMap(result => ([new Action1(result), new Action2(result)])
这个答案可能对其他寻求解决多个操作效果的人有帮助。
正如其他人已经回答的那样,
您可以在一个效果中调度多个动作(返回动作数组,或使用存储来调度(this.store.dispatch(otherAction()) - 但不行!
您不应该在一个效果中分派多个操作,因为它是反模式(https://github.com/timdeschryver/eslint-plugin-ngrx/blob/main/docs/rules/no-multiple-actions-in -效果.md)
解决方案:效果链接(一种效果触发另一种效果)
updateAPILoadingState$ = createEffect(()=>{
return this.action$.pipe(
ofType(getAPIAction), // <-- same action which below effects uses to update loading status
exhaustMap(()=>{
return updateLoadingState("LOADING")
})
)
})
getSomeInformationFromAPI$ = createEffect(()=>{
return this.action$.pipe(
ofType(getAPIAction), // <--- Listens to the Action
exhaustMap(()=>{
return this.apiService.getSomething().pipe(
map((apiResponse)=>
postAPISuccess(apiResponse)) // <-- trigger action to save the response
})
)
})
postAPISuccessEffect$ = createEffect(()=>{
return this.action$.pipe(
ofType(postAPISuccess), // <--- EFFECTS CHAIN : listen to the action which was triggered by above effect
exhaustMap(()=>{
return updateLoadingState("LOADED")
)
})
当然,其他答案公平地提到您可以使用注入的
Store
引用或 switchMap
来分派多个操作,但值得注意的是,这不被认为是一个特别好的做法,因为它在某些情况下可能会掩盖意图,并使其他影响(由此触发的影响)变得更难以推理。您可以在here找到如何克服这一问题的详细说明,但简单来说,一个效果应该只调度一个且仅一个操作,然后其他效果(或减速处理程序)也应该另外监听该一个操作。我提供的链接还提供了如何将代码更改为更正确版本的示例。
private _getAllEntreprises = createEffect(() =>
this.actions$.pipe(
ofType(EntrepriseActions.getAllEnterprises),
switchMap(({ query, page }) =>
this.service
.getAllEntreprises(page, query)
.pipe(
exhaustMap
((response) => {
return[
EntrepriseActions.getCurrentPage({current:response.current_page}),
EntrepriseActions.getTotalPages({ total: response.total_pages }),
EntrepriseActions.getAllEnterprisesCompleted({entreprises:response.enterprises}),
SettingsActions.loading({ loading: false }),
SettingsActions.successMsg({ message: response.message }),
]})
)
)
)
);