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

Angular错误处理实现:区分错误场景实现通知展示或页面跳转

方案合理性判断

你提出的自定义错误类层级的方案完全合理,核心优势如下:

  • 完全和后端实现解耦,无需修改后端响应结构,不会影响其他调用方使用API
  • 错误处理逻辑收敛在业务侧,全局错误处理器只需要根据错误类的类型执行对应的通用逻辑,不需要感知业务场景差异
  • 后续新增业务场景只需要扩展新的错误子类即可,符合开闭原则
更优的落地思路(适配你当前NgRx技术栈,无需大改现有逻辑)

步骤1:统一封装错误转换逻辑,避免重复代码

先定义业务错误类层级,再封装公共工具把HttpErrorResponse转换为对应的自定义错误实例,逻辑放在公共工具层,不需要每个业务模块重复开发:

// 基础业务错误类
export class BusinessError extends Error {
  constructor(public statusCode: number, public message: string) {
    super(message);
    this.name = 'BusinessError';
  }
}

// 无权限错误类
export class NoPermissionError extends BusinessError {
  constructor(message: string) {
    super(403, message);
    this.name = 'NoPermissionError';
  }
}

// 资源不存在错误类
export class ResourceNotFoundError extends BusinessError {
  constructor(message: string, public scene?: string) {
    super(404, message);
    this.name = 'ResourceNotFoundError';
  }
}

// 公共错误转换工具
export function convertHttpError(error: HttpErrorResponse): BusinessError {
  switch(error.status) {
    case 403:
      return new NoPermissionError(error.error?.message || '您无权限访问该资源');
    case 404:
      return new ResourceNotFoundError(error.error?.message || '请求的资源不存在');
    default:
      return new BusinessError(error.status, error.error?.message || '操作失败,请稍后重试');
  }
}

修改orderService直接复用转换逻辑,不需要改上层调用代码:

public getOrders(): Observable < Order[] > {
  return this.http.get < Order[] > (this.api.getUrl('api/orders'), this.api.getHeaders())
    .pipe(
      catchError((err: HttpErrorResponse) => throwError(() => convertHttpError(err)))
    )
}

步骤2:拆分通用错误和业务专属错误的处理逻辑

  • 通用逻辑(比如403全局跳转首页)放在全局错误处理器中统一处理,不需要每个业务场景重复实现:
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  constructor(private router: Router, private toast: ToastService) {}

  handleError(error: unknown): void {
    if (error instanceof NoPermissionError) {
      this.toast.error(error.message);
      this.router.navigate(['/home']);
      return;
    }
    // 其他通用逻辑:500错误上报日志、网络异常提示等
  }
}
  • 业务专属逻辑(比如订单列表的404要显示「当前暂无订单」提示)放在对应业务的Effect中监听失败Action处理即可,修改你原有的失败Action定义,把传递errorMessage改为传递完整错误实例:
// Effect中的catchError修改
catchError((error: BusinessError) => of(SurveyActions.getOrdersFailure({ error })))

// 新增订单请求失败处理Effect
handleOrderFail$ = createEffect(
  () => this.actions$.pipe(
    ofType(OrderActions.getOrdersFailure),
    map(({ error }) => {
      if (error instanceof ResourceNotFoundError) {
        this.toast.info('当前暂无订单');
      } else {
        this.toast.error(error.message);
      }
    })
  ),
  { dispatch: false }
)

可选优化:错误逻辑多态实现

如果后续业务场景增多,不想写大量if判断,可以给错误类新增handle方法,不同错误类型自己实现处理逻辑,调用方直接执行即可:

export class ResourceNotFoundError extends BusinessError {
  constructor(message: string, public scene?: string) {
    super(404, message);
    this.name = 'ResourceNotFoundError';
  }

  handle(toast: ToastService) {
    if (this.scene === 'orderList') {
      toast.info('当前暂无订单');
    } else {
      toast.error(this.message);
    }
  }
}

// 调用方不需要判断类型,直接执行
error.handle(this.toast);

内容的提问来源于stack exchange,提问作者matikowy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:00:03