Fetch API错误处理问题:无法正确获取API返回的错误信息
解决Fetch处理API错误的两难问题
我太懂你这个困扰了——用fetch处理API返回的业务错误时,确实容易陷入“要么抓不到API错误,要么误触发成功action”的两难。咱们先理清楚问题根源,再给你一个靠谱的解决方案。
问题根源
fetch的设计很“特殊”:只有当网络层面彻底失败(比如断网、域名解析失败)时,才会自动抛出错误进入catch。哪怕API返回401、400这类业务错误状态码,fetch都会认为请求“成功”,直接进入.then流程。
- 你第一段代码里
throw response,抛出去的是Response对象,不是API返回的错误JSON,所以catch里拿到的不是后端给的具体错误信息; - 第二段代码跳过
response.ok判断,不管状态码如何都解析JSON然后走成功action,哪怕后端返回的是错误内容。
正确的处理方式
核心思路是:先统一解析响应体,再根据状态码或返回内容判断是成功还是失败,把API返回的错误JSON主动抛进catch里。
修改后的代码如下:
export const signIn = data => dispatch => { dispatch({ type: SIGN_IN }); fetch(`${API_URL}/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(data), }) .then(response => { // 先解析响应体,不管状态码是否正常 return response.json().then(json => { // 如果状态码非2xx,把解析后的错误JSON抛出去 if (!response.ok) { throw json; } // 状态码正常,返回成功数据 return json; }); }) .then(json => { dispatch({ type: SIGN_IN_SUCCESS, payload: json }); localStorage.setItem("token", 'Bearer ' + json.token); localStorage.setItem("user", JSON.stringify(json.user)); }) .catch(err => { // 这里的err要么是网络错误,要么是API返回的错误JSON dispatch({ type: SIGN_IN_FAILED, payload: err }); }); };
额外优化点
如果你的后端习惯用200状态码,但通过返回体里的字段(比如success: false或code: 400)标识错误,那可以把判断逻辑换成基于返回内容:
.then(response => response.json()) .then(json => { // 假设后端用success字段标识请求是否成功 if (!json.success) { throw json; } return json; })
这样不管后端用什么状态码,都能准确捕获业务错误,同时只有真正成功时才会触发登录成功的action。
内容的提问来源于stack exchange,提问作者Merim
相关产品推荐
相关产品推荐

