在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
相关产品推荐
相关产品推荐

