网络宝典
第二套高阶模板 · 更大气的阅读体验

fetch错误处理机制详解

发布时间:2025-12-11 01:45:29 阅读:171 次

用 fetch 发请求现在很常见,但很多人一开始都会踩同一个坑:以为网络出问题或者接口报错时,fetch 会自动进 .catch。其实不是这样。

fetch 并不总是抛错

比如你发了个请求,服务器返回了 404 或 500,这时候 fetch 的 Promise 并不会被拒绝。只有在真正“网络异常”的时候,比如断网、DNS 解析失败、请求根本发不出去,才会触发 catch。

这意味着,哪怕后端崩了返回 500,只要请求能通,fetch 就算“成功”了。真正的错误处理得你自己判断。

怎么正确判断响应是否出错?

你需要检查响应的 ok 属性。这个属性为 true 时表示状态码是 2xx,否则就是有问题。

fetch('/api/user')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(err => {
    console.error('Fetch failed: ', err);
  });

也可以用 status 判断具体问题

有时候你想区分是 404 还是 500,可以自己根据 status 做不同提示。比如用户访问了一个不存在的页面,你可以提醒“内容没找到”,而如果是服务器内部错误,就提示“系统开小差了”。

fetch('/api/post/123')
  .then(res => {
    if (res.status === 404) {
      showNotFound();
    } else if (res.status >= 500) {
      showServerError();
    } else if (res.ok) {
      return res.json();
    }
  })
  .then(data => {
    if (data) updateUI(data);
  });

别忘了网络异常的情况

虽然上面处理了 HTTP 状态,但真遇到断网或请求超时,就得靠 catch 来兜底。可以给用户一个友好提示,比如“网络不给力,请检查连接”。

加上超时控制更稳妥

fetch 默认没有超时,如果服务器一直不回,页面就卡着。可以自己加个限时逻辑:

const controller = new AbortController();

// 5 秒后中断请求
setTimeout(() => controller.abort(), 5000);

fetch('/api/slow-data', { signal: controller.signal })
  .then(res => {
    if (!res.ok) throw new Error('Bad response');
    return res.json();
  })
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Request timed out');
    } else {
      console.error('Error: ', err);
    }
  });

这种写法适合那些对响应速度敏感的功能,比如搜索建议、实时状态更新。

实际开发中的小技巧

可以把通用的错误处理封装成函数,避免每个请求都重复写。比如写个 safeFetch,统一处理状态码、JSON 解析和超时。

另外,调试时多看浏览器的 Network 面板,能清楚看到请求发出没有、响应码是多少,比光看控制台快多了。