fetch不会自动将404、500等http错误视为异常抛出,仅在网络层失败(如断网、dns错误)时reject并进入catch;服务器返回404/500时fetch仍resolve,需手动检查response.ok或response.status并主动throw才能触发错误处理。

fetch 不会自动把 404、500 当作错误抛出,网络断开才进 catch;必须手动检查 response.ok 或 response.status 才能捕获 HTTP 错误。
为什么 .catch() 捕不到 404 和 500
因为 fetch 的 Promise 只在网络层失败时 reject:比如 DNS 解析失败、连接被拒、CORS 被拦、URL 拼错导致 TypeError: Failed to fetch。而服务器返回 404 或 500,fetch 仍认为“通信成功”,返回一个 Response 对象,response.ok 是 false,response.status 是 404/500 —— 但你已经进了 .then() 分支。
- 常见错误写法:
fetch('/api/user').then(res => console.log(res.status)),即使返回 500,也会打印500,不会触发catch - 真实网络错误示例:
TypeError: Failed to fetch(断网)、TypeError: Load failed(CORS 阻止) - HTTP 错误不是异常,是服务器的合法响应,只是语义上“失败”了
用 async/await 统一处理两类错误
比起链式 .then().catch(),async/await 更容易把网络错误和 HTTP 错误收拢到同一个 try/catch 块里。
- 在
await fetch(...)后立即检查response.ok,不满足就throw new Error(...) - 这样无论网络失败还是 HTTP 状态码异常,都会被
catch捕获 - 避免在
.then()里重复写错误判断逻辑
async function getUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
return await res.json();
} catch (err) {
// 这里能拿到 TypeError(网络) 和自定义 Error(HTTP)
console.error('请求失败', err.message);
throw err;
}
}
如何区分网络错误和 HTTP 错误做不同响应
有些场景需要差异化处理:比如网络错误提示“请检查网络”,而 404 提示“找不到该用户”,500 提示“服务暂时不可用”。这时得从 err 类型和内容入手。
- 网络错误通常是
TypeError实例,err.name === 'TypeError',且err.message包含Failed to fetch或Load failed - HTTP 错误是你自己
throw的,可以用err instanceof Error+ 自定义属性(如err.type = 'http')标记 - 注意:不要依赖
res.status在catch里读取——网络错误时res根本不存在
fetch 重试时别漏掉 HTTP 错误判断
加重试逻辑时,如果只重试网络错误,却对 404/500 直接放弃,可能掩盖配置问题(比如 API 路径写错却反复重试)。要明确哪些状态码值得重试。
- 通常只对 5xx(
res.status >= 500)或超时类错误重试,4xx 属于客户端问题,重试无意义 - 重试函数里,
if (!res.ok && res.status >= 500)才递归调用自身 - 别在重试前就
await res.json(),否则 500 响应体为空或非 JSON 会额外抛出SyntaxError
最易被忽略的一点:HTTP 错误的响应体可能含调试信息(比如后端返回的 { "error": "DB connection failed" }),但很多人只检查 status 就 throw,没读取 res.text() 或 res.json(),结果日志里只有 “HTTP 500”,没有上下文。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











