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

在Rxjs Epic中使用Fetch捕获HTTP响应错误并获取详情

解决方案:在RxJS管道中处理HTTP错误响应详情

问题说明

在React项目中使用RxJS处理API请求时,需要获取HTTP错误响应(比如400请求里的验证失败详情),但常规catchError没法直接拿到完整的错误响应对象——因为HTTP客户端会在非2xx状态时直接抛出错误,导致错误根本到不了处理正常响应的map操作符。得在请求初期拦截错误响应,同时不影响正常响应的处理流程。

原代码

action$.pipe(
    ofType(DataActionEnum.Fetch_Data),
    withLatestFrom(state$),
    mergeMap(([action, state]: [IFetchDataAction, IApplicationState]) => {
      return DataAPIClient.get<any>(`Position?assets=${action.asset}`).pipe(
        //catchError((err: any, caught: any) => {
        //  if (err.code === 400) {
        //    return of(FetchDataFailureAction("x"), sendToast("Test", ToastType.Error));
        //  }
        //}),
        // map((res: any) => {
        //   if (res.ok) return res.json();
        //   const x = res.status;
        //   throw res;
        // }),
        map((response) => {
          if (response.status === 400) {
            const error = response.data;
            return of(FetchDataFailureAction(error), sendToast(error, ToastType.Error));
          }
          const data = response.data;
          return FetchDataSuccessAction(data);
        }),
        catchError((x: any) => {
          const error = "API Issue - " + x.message;
          return of(FetchDataFailureAction(x.message), sendToast(error, ToastType.Error));
        })
      );
    })
  );

解决步骤与修改后代码

1. 调整HTTP客户端配置(关键前提)

先确保你的DataAPIClient不会在非2xx状态码时自动抛出错误。如果是基于Axios封装的客户端,加个validateStatus配置:

// Axios配置示例
const DataAPIClient = axios.create({
  // 其他原有配置
  validateStatus: (status) => true // 让所有状态码都进入响应流,不自动抛错
});

如果是自己封装的Fetch工具,也要保证即使状态码不是2xx,也返回响应对象而非抛出错误。

2. 在RxJS管道中统一处理响应

修改管道逻辑,在map里同时处理成功和错误响应,真正的网络错误(比如请求超时、断网)再交给catchError处理:

action$.pipe(
  ofType(DataActionEnum.Fetch_Data),
  withLatestFrom(state$),
  mergeMap(([action, state]: [IFetchDataAction, IApplicationState]) => {
    return DataAPIClient.get<any>(`Position?assets=${action.asset}`).pipe(
      map((response) => {
        // 处理2xx范围内的成功响应
        if (response.status >= 200 && response.status < 300) {
          return FetchDataSuccessAction(response.data);
        } 
        // 处理4xx/5xx的业务错误响应
        else {
          const errorDetails = response.data;
          // 用concat确保多个Action都能被触发
          return concat(
            of(FetchDataFailureAction(errorDetails)),
            of(sendToast(errorDetails, ToastType.Error))
          );
        }
      }),
      // 处理请求本身失败的网络错误(比如断网、超时)
      catchError((networkError) => {
        const errorMsg = `API请求失败: ${networkError.message}`;
        return concat(
          of(FetchDataFailureAction(errorMsg)),
          of(sendToast(errorMsg, ToastType.Error))
        );
      })
    );
  })
);

关键说明

  • 统一响应处理:让客户端返回所有状态码的响应后,就能在同一个map里直接拿到错误响应的data字段,轻松获取验证失败这类详情。
  • 区分两类错误:map处理HTTP状态码对应的业务错误,catchError处理请求本身失败的网络错误,逻辑划分更清晰。
  • 多Action触发:如果要同时返回多个Action,必须用concat或merge包裹of(),不然只会执行第一个Action。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:02:36