Fetch不会自动将404或500视为错误抛出,因其设计将“通信完成”与“业务成功”分离:只要服务器返回响应(无论状态码),Promise即resolve进入.then();仅网络层彻底失败(如断网、DNS错误、CORS拦截)才reject进.catch()。

Fetch 不会自动把 404 或 500 当作错误抛出,是因为它的设计逻辑把“通信是否完成”和“业务是否成功”分开了——只要请求发出去、服务器有响应(哪怕返回的是错误页),就算“通信成功”,Promise 就会进入 .then();只有网络层面彻底失败(比如断网、DNS 解析失败、CORS 被拦、URL 写错)时,才会 reject 并进 .catch()。
为什么 404/500 不触发 catch
浏览器认为:你发了请求,服务器也回了包,链路是通的。至于服务器说“找不到资源”或“内部出错”,那是业务语义,不是网络问题。所以:
- response.ok 是 false(因为 404/500 不在 200–299 范围内)
- response.status 是 404 或 500
- Promsie 依然 resolve,不会跳到 .catch()
怎么手动捕获 HTTP 错误
必须在第一个 .then() 里检查响应状态,并主动 throw 错误,才能让后续的 .catch() 或 try/catch 生效:
- 用 if (!response.ok) throw new Error(...)
- 或者更细粒度地判断:if (response.status >= 400) throw new Error(...)
- throw 后,后续的 .catch() 或 await 的 try/catch 就能统一处理
完整处理示例(推荐写法)
兼顾网络错误、HTTP 错误、JSON 解析失败三类问题:
立即学习“Java免费学习笔记(深入)”;
- 先检查 response.ok,不成立就 throw
- 再调用 response.json(),它本身可能 reject(比如返回空体或非法 JSON)
- 外层用 try/catch 或 .catch() 捕获所有异常
额外注意点
有些情况容易混淆,需要单独处理:
- 控制台仍显示 404 报错:这是浏览器自动记录的网络警告,JavaScript 无法屏蔽,但不影响逻辑;只要你不依赖它报错,而是自己检查 status,就不会漏处理
- response.json() 可能失败:即使 status 是 200,如果后端返回空响应或格式错乱的 JSON,response.json() 会抛 SyntaxError,需单独 try/catch 或放在同一级错误流中处理
- 超时和取消:fetch 本身不支持 timeout,要用 AbortController 配合 signal 控制


















