NgRx Effects:在CatchError中同时派发Action并返回错误
Angular NgRx Effect:监听错误同时传递给全局拦截器
我需要实现一个NgRx Effect,在API请求失败时,既要派发addItemFailure动作,又要把HttpErrorResponse传递给全局错误处理器,而不是在这里捕获错误。
最初的写法因为双重return无法运行,但能体现需求:
addItem$ = createEffect((): Observable<Action> => { return this.action$.pipe( ofType(ItemActions.addItem), exhaustMap((action) => { return this.apiClient.addItem(action.itemModel).pipe( map((response) => ItemActions.addItemSuccess({ response })), catchError((exception: HttpErrorResponse) => { return throwError(() => exception); return of(ItemActions.addItemFailure({ exception })); }), ); }), ); });
单独使用任意一个return都能正常工作,但无法同时达成两个目标。我尝试过直接调用store.dispatch或者在throwError的工厂函数里dispatch,均未成功:
第一种尝试:
catchError((exception: HttpErrorResponse) => { this.store.dispatch(ItemActions.addItemFailure({ exception })); return throwError(() => exception); }),
第二种尝试:
catchError((exception: HttpErrorResponse) => { return throwError(() => { this.store.dispatch(ItemActions.addItemFailure({ exception })); return exception; }); })
正确解决方案
在catchError中返回一个合并的Observable,先派发失败动作,再抛出错误。使用concat确保动作先被派发,之后错误再传递给全局拦截器:
import { concat } from 'rxjs'; // ... addItem$ = createEffect((): Observable<Action> => { return this.action$.pipe( ofType(ItemActions.addItem), exhaustMap((action) => { return this.apiClient.addItem(action.itemModel).pipe( map((response) => ItemActions.addItemSuccess({ response })), catchError((exception: HttpErrorResponse) => { // 按顺序执行:先派发失败动作,再抛出错误 return concat( of(ItemActions.addItemFailure({ exception })), throwError(() => exception) ); }), ); }), ); });
为什么之前的写法不行
- 直接调用
this.store.dispatch违反了NgRx Effect的最佳实践:Effect应该通过返回Observable来派发动作,而非直接调用store方法,在严格模式下还会触发错误。 - 在
throwError的工厂函数里dispatch,执行时机不可靠,且错误抛出后流会立即终止,可能导致动作派发不生效。
内容的提问来源于stack exchange,提问作者Jeffrey Roosendaal
相关产品推荐
相关产品推荐

