前端架构实战:当服务器关闭时,如何优雅提示 502 错误?

前端架构实战:当服务器关闭时,如何优雅提示 502 错误?

在开发与运维过程中,后端服务重启或宕机是常有的事。此时,Nginx 会向浏览器返回 502 Bad Gateway 状态码。

默认情况下,Axios 会抛出 Request failed with status code 502 这样的原始错误信息。这对普通用户来说不仅晦涩难懂,还容易引起恐慌。作为前端架构师,我们需要在全局拦截器层面"消化"这些技术性错误,给用户展示友好的提示。

本文将带你优化 common.js 中的响应拦截器,实现对服务不可用状态的优雅处理。

一、 核心修复逻辑

我们需要在响应拦截器的异常处理函数中,对 HTTP 状态码进行分层处理。优先处理服务器故障类错误(502/503/504),其次是业务限流(429),最后才是常规的业务异常。

以下是优化后的 common.js 异常处理部分代码:

javascript 复制代码
// ==================== B. 异常响应 (401, 429, 500, 502 等) ====================
async function (error) {
  const originalRequest = error.config;
  const response = error.response;
  // -----------------------------------------------------
  // 1. 服务器故障类拦截 (502, 503, 504)
  // -----------------------------------------------------
  if (response) {
    const status = response.status;
    // 502: 网关错误(后端服务未启动或Nginx连接不上后端)
    // 503: 服务不可用(后端服务过载或正在维护)
    if (status === 502 || status === 503) {
      return Promise.reject("服务器正在维护或已关闭,请稍后再试");
    }
    // 504: 网关超时(后端处理时间过长)
    if (status === 504) {
      return Promise.reject("网络连接超时,请重试");
    }
  } else if (error.message.includes('Network Error')) {
    // 服务器完全没响应(连 Nginx 都没开)或者本地断网
    // 此时 response 对象不存在,需要通过 error.message 判断
    return Promise.reject("无法连接到服务器,请检查网络");
  }
  // -----------------------------------------------------
  // 2. 429 限流拦截
  // -----------------------------------------------------
  if (response && response.status === 429) {
    const msg = (response.data && response.data.errorMsg) 
                ? response.data.errorMsg 
                : "请求过于频繁,请稍后再试";
    return Promise.reject(msg); 
  }
  // -----------------------------------------------------
  // 3. 401 主动刷新逻辑
  // -----------------------------------------------------
  if (
    response &&
    response.status === 401 &&
    !originalRequest.url.includes("/user/refresh") &&
    !originalRequest._retry
  ) {
      // ... (此处保持你原有的 Token 刷新逻辑不变) ...
      // 注意:如果服务端 502,上面已经拦截并 reject 了,不会走到这里。
      // 只有状态码确实是 401 时才会进入此分支。
  }
  // -----------------------------------------------------
  // 4. 最终兜底:状态码映射与默认提示
  // -----------------------------------------------------
  // 定义常见 HTTP 状态码的友好提示映射
  const statusTextMap = {
    400: "请求参数错误",
    404: "请求资源不存在",
    405: "请求方式不正确",
    500: "服务器内部异常"
  };
  // 优先取后端返回的 errorMsg,其次取映射表文案,最后兜底
  const finalMsg = (response && response.data && response.data.errorMsg) 
                   ? response.data.errorMsg 
                   : (response && statusTextMap[response.status])
                   ? statusTextMap[response.status]
                   : (error.message || "系统繁忙");
  return Promise.reject(finalMsg);
}

二、 架构原理解析

为什么这样修改能解决问题?
1. 状态码优先级拦截

我们在代码最前端增加了对 502、503 的判断。一旦检测到这些状态码,直接返回固定的友好文案,阻断后续逻辑。这样避免了将这些错误传递到后续的业务逻辑中。
2. 区分"无响应"与"错误响应"

当服务器完全关闭(甚至连 Nginx 都没开)时,Axios 收不到 HTTP 响应,此时 error.response 为 undefined。

代码通过 error.message.includes('Network Error') 准确捕捉了这种底层网络中断的情况。
3. 状态映射表

通过 statusTextMap 对象,我们将常见的 HTTP 错误码(400, 404, 500)集中管理。如果后端没有返回详细的 errorMsg,前端会自动根据状态码显示"请求参数错误"或"服务器内部异常",而不是原生的英文堆栈信息。
4. 消除技术术语

原来的 error.message 可能包含 Request failed with status code... 这种技术术语。经过上述重构,用户看到的将只有你定义的中文提示语,体验更加统一。

三、 测试建议

修改完成后,建议进行以下测试以确保逻辑生效:

  1. 模拟 502:停掉 Spring Boot 后端服务,但保留 Nginx 运行。此时 Nginx 找不到后端会报 502。刷新前端点击按钮,应提示"服务器正在维护或已关闭,请稍后再试"。
  2. 模拟网络断开:直接把后端服务和 Nginx 全部关闭。点击按钮应提示"无法连接到服务器,请检查网络"。
  3. 清理缓存 :修改完 JS 文件后,记得在浏览器强制刷新(Ctrl + F5)清理缓存。
    通过这种全局层面的容错处理,你的前端应用在面对后端服务波动时,将表现出更高的健壮性和专业度。
相关推荐
不会就选b9 小时前
Linux之TCP理论<1>
linux·运维·服务器
小π军10 小时前
操作系统面试题
java·linux·服务器
用户0333074139511 小时前
TypeScript using 与 AsyncDisposableStack:在真实服务端代码中协调多资源清理
前端
daisychey11 小时前
用 Playwright 做多平台内容分发,我踩过的 8 个坑
前端
架构师那点事儿11 小时前
大模型如何私有化部署到生产环境
人工智能·架构·llm
Android系统攻城狮11 小时前
Linux Gstreamer深度解析之gst_audio_encoder_get_frame_samples_min调用流程与实战(六十)
linux·运维·服务器·音视频·gstreamer音视频·音视频进阶·gstreamer音视频进阶
IT_陈寒12 小时前
为什么你应该学习JavaScript?
前端·人工智能·后端
大龄秃头程序员12 小时前
iOS冷启动监控Demo
前端
lightning_bug12 小时前
Windows系统Docker+SpringBoot+H5+Mysql+Redis打包部署流程
后端·架构
光影少年12 小时前
为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?
前端·javascript·算法