You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 15:39:04