fetch 的 catch 仅捕获网络异常(如断网、DNS 失败、CORS 拦截),不捕获 404/500 等 HTTP 错误;后者需通过 res.ok 或 res.status 手动判断并 throw,再统一在 try/catch 中处理。

它会触发 catch,但只在真正网络出问题时——比如断网、DNS 解析失败、跨域被拦截、HTTPS 混合内容被阻止。而 404、500 这类 HTTP 错误,fetch 认为“请求发出去了,服务器也回了话”,所以 Promise 仍进入 then,不会进 catch。
为什么 catch 不捕获 404/500?
这是 fetch 的设计原则:只要拿到响应(哪怕状态码是 500),就算“网络成功”。只有请求根本没发出去或中途断掉,才会 reject 并触发 catch。
- ❌ 进 catch 的情况:用户离线、域名拼错、CORS 报错、SSL 证书异常、AbortController 中止
- ✅ 不进 catch 但需手动处理的情况:服务器返回 401、404、500、503 —— 此时
res.ok === false,res.status是对应数字
怎么判断 response.ok 状态?
response.ok 是最简洁可靠的判断依据:它等价于 response.status >= 200 && response.status 。只要不是 2xx,它就是 <strong>false</strong>。
- 在
await fetch(...)后立刻检查:if (!res.ok) throw new Error(...) - 也可以用
res.status做更细粒度判断,比如区分 401(登录过期)和 500(服务异常) - 注意:
res.ok不代表业务成功,只是 HTTP 层“看起来正常”;后续还要校验data.code === 0或data.success === true等业务字段
推荐的错误处理结构(async/await)
把网络异常和 HTTP 异常统一到一个 catch 里,逻辑清晰且不易遗漏:
- 用 try 包住整个 fetch + 解析流程
- fetch 成功后立即检查
!res.ok,手动 throw - 再调用
res.json()—— 它可能因返回非 JSON(如 HTML 错误页)抛出 SyntaxError,也会落到同一个 catch - 这样,网络错误、HTTP 错误、解析错误,都能被集中处理
不复杂但容易忽略。


















