fetch 遇到 500 错误不进 catch,因其仅在网络层失败(如断网、dns 错误)时 reject;500 属服务器响应,fetch 仍 resolve 并返回 ok=false、status=500 的 response 对象,需手动检查并抛错。

fetch 遇到 500 错误时不会自动进入 catch,必须手动检查响应状态,再决定是否抛出错误、提示用户或重试。
为什么 500 不进 catch?
fetch 只在网络层失败(如断网、DNS 错误、CORS 拒绝)时 reject Promise;而服务器返回 500,它仍会 resolve 并给出一个 Response 对象——此时 response.ok === false,response.status === 500,但你不会掉进 catch 分支。
- 错误写法:
fetch(...).then(res => console.log(res.status))—— 即使是 500,也会执行到这里 - 正确前提:用
async/await+try/catch统一控制流,再主动判断状态
怎么捕获并提取有用信息?
拿到 Response 后,先检查 !res.ok,再尝试读取 JSON 格式的错误体(服务端通常会在 500 响应中返回 { "message": "..." }):
- 用
if (!res.ok) { throw await res.json(); }获取后端自定义错误消息 - 兜底处理:
error?.message || `服务异常(${res.status})`,避免读取undefined - 不依赖
res.statusText(如 "Internal Server Error"),它对用户无意义
怎么给用户友好提示?
500 是服务端问题,前端不能修复,但要让用户感知可控、可预期:
- 文案示例:“服务暂时不可用,请稍后再试”“数据加载失败,我们正在紧急处理”
- 配合 UI:禁用触发按钮、显示“重试”按钮、切换到带图标的空状态页
- 绝不暴露原始堆栈、URL、请求体、响应体等敏感或技术细节
要不要自动重试?
仅对安全的请求(如 GET 查询)考虑有限重试,且必须加约束:
- 最多 2–3 次,首次延迟 1 秒,后续可用指数退避(1s → 2s → 4s)
- 页面初始化自动请求建议只试 1 次;用户点击触发的才开启重试逻辑
- 重试前检查是否已取消、是否超时、是否在离线状态,避免无效请求雪崩
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











