Angular路由Resolver搭配Ngrx Data服务的报错无法处理问题
NGRX Data Resolver 加载错误处理方案
问题根源
你的race实现不生效核心有两个原因:
errors$是事件流,仅会在错误发生时推送新值,你原来的代码把getAll()放在loaded$的tap回调中才触发,此时race对errors$的订阅已经初始化,可能会漏掉getAll()抛出的错误事件;- 直接用
mapTo(true)会导致即使加载失败,resolver也返回成功状态,不符合错误处理的预期逻辑。
修复后的实现
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { Observable, race, of } from 'rxjs'; import { filter, first, tap, mapTo, catchError } from 'rxjs/operators'; import { ExerciseEntityService } from './exercise-entity.service'; @Injectable() export class ExercisesResolver implements Resolve<boolean> { constructor( private exercisesService: ExerciseEntityService, private router: Router ) {} resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> { // 先触发数据加载,保证错误事件能被后续订阅捕获 if (!this.exercisesService.loaded) { this.exercisesService.getAll(); } return race( // 加载成功分支 this.exercisesService.loaded$.pipe( filter(loaded => !!loaded), first(), mapTo(true) ), // 加载失败分支 this.exercisesService.errors$.pipe( first(), tap(() => { // 错误时跳转到错误页,可根据业务需求调整逻辑 this.router.navigate(['/error']); }), mapTo(false), // 兜底避免流异常导致resolver卡死 catchError(() => of(false)) ) ); } }
核心修改点
- 把
getAll()触发逻辑移到流外部,确保订阅errors$之前就已经发起加载请求,不会漏掉错误事件; - 错误分支中加入跳转逻辑,返回
false标识加载失败,也可根据业务需求修改为抛出错误在路由全局拦截器中统一处理; - 新增
catchError兜底逻辑,避免流抛出未捕获异常导致resolver永远无法完成解析。
内容的提问来源于stack exchange,提问作者javifm
相关产品推荐
相关产品推荐

