NgRx Effect从store取值后调用服务的类型错误及catchError配置问题
错误原因梳理
1. 初始类型报错的根因
- 误用
map操作符:map只会对输入值做普通转换,你在回调内返回from(getData())得到的是Observable<Action>,最终store$流的输出类型会变成Observable<Observable<Action>>,不符合NgRx Effect要求的Observable<Action>类型,所以需要换成高阶打平操作符(比如你用到的switchMap,也可以和外层保持一致用exhaustMap匹配取消策略),自动把内层Observable打平为一阶流。 - 缺少return语句:你最初的代码里
map(name => { from(...) })用花括号包裹了函数体,没有显式写return,相当于返回undefined,自然无法匹配类型要求。
2. catchError的正确放置逻辑
你需要捕获的是getData()请求过程中的错误,所以要把catchError放在内层请求流的pipe里,不要放在外层store选择流的位置:
- 如果放在store选择流外层,只能捕获store select阶段的错误,请求阶段的错误会穿透到外层,导致Effect主流程终止
- 内层的catchError捕获请求错误后,返回合法的Action,不会打断整个Effect的后续运行
注意:RxJS流的错误会向下传播,如果不在请求内层捕获错误,错误会冒泡到Effect主流程,直接销毁整个Effect,后续再也不会响应对应的action。
完整可运行代码
public loadData = createEffect(() => this.actions$ .pipe( ofType(myActions.loadData), exhaustMap(_ => this.store$.pipe( tap(_ => { this.logger.info(`loadData`)}), select(fromApp.getName), first(), switchMap(name => from(this.getData(name)) .pipe( map(data => myActions.loadDataSuccess(data)), // catchError放在请求流内部,捕获请求阶段所有错误 catchError(error => { this.logger.error(`loadData: ${error}`); return of(myActions.loadDataError(error)); }) ) ) ) ) ) ); /** Service call **/ private async getData(name: string): Promise<DataState[]> { // 业务逻辑实现 }
内容的提问来源于stack exchange,提问作者peterc
相关产品推荐
相关产品推荐

