Fetch API 仅在网络异常(如断网、DNS失败)时reject,404/500等HTTP错误仍resolve,需手动检查response.ok或status来处理业务错误。

Fetch API 本身不会因 HTTP 状态码(如 404、500)抛出错误,只有网络断连、DNS 失败、请求被阻止等底层异常才会触发 catch。所以要用 try...catch 捕获网络层异常,关键在于:只靠 catch 不够,还需手动检查 response.ok 或 response.status 来处理业务级错误。
捕获真正的网络层异常(如离线、跨域拒绝、URL 无效)
fetch() 在遇到无法发起请求的情况时(例如用户没联网、域名解析失败、HTTPS 混合内容被拦截),会返回一个被 reject 的 Promise,这时 catch 才会执行。
- 这类异常通常对应
TypeError,比如"Failed to fetch"或"NetworkError when attempting to fetch resource" - 不是所有浏览器都把 4xx/5xx 当错误抛出——这是 Fetch 的设计原则:HTTP 错误仍是“成功响应”,只是状态码不为 2xx
- 示例:断网状态下调用
fetch('https://api.example.com/data')会进catch
必须手动检查 response.ok 或 status,否则 404/500 不会进 catch
即使服务器返回 404,fetch 仍会 resolve 并进入 then,因为请求已发出且收到了响应。要把它当错误处理,得自己判断:
- 用
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`) - 或更细粒度地判断:
if (response.status >= 400 && response.status - 注意:
response.statusText在某些环境(如 Chrome 的 CORS 响应)可能为空字符串,建议结合 status code 使用
完整写法:try catch + response.ok 检查 + await
推荐使用 async/await 配合 try...catch,结构清晰且能统一捕获网络异常和业务异常:
立即学习“Java免费学习笔记(深入)”;
async function fetchData() {
try {
const res = await fetch('/api/users');
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return await res.json();
} catch (err) {
if (err.name === 'TypeError' && err.message.includes('fetch')) {
console.error('网络层异常:请求未发出,可能是离线、跨域失败或 URL 错误');
} else {
console.error('业务异常或 HTTP 错误:', err.message);
}
throw err; // 重新抛出,便于上层处理
}
}
补充建议:超时控制不能靠 fetch 原生支持
Fetch API 本身没有 timeout 选项,网络卡住时 Promise 会一直 pending,catch 不会触发。需手动实现超时:
- 用
Promis.race([fetch(...), timeoutPromise])包装 - 或封装一个带 AbortController 的版本,在指定时间后调用
abort(),此时 fetch 会 reject 并抛出AbortError - AbortError 属于网络层异常,会被
catch捕获,可单独识别处理


















