前端架构实战:当服务器关闭时,如何优雅提示 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. 状态码优先级拦截

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

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

代码通过 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)清理缓存。
    通过这种全局层面的容错处理,你的前端应用在面对后端服务波动时,将表现出更高的健壮性和专业度。
相关推荐
lilihuigz3 小时前
AI内容管理系统全面解析:核心功能、关键技术与架构应用指南 - WP站长
人工智能·搜索引擎·架构
wordbaby3 小时前
如何封装一个生产级的 React Native 分页列表 Hook
前端·react native·react.js
小帅不太帅4 小时前
我做了两个工具,一个 7MB 的壳,一个会记住的壳
前端·app·产品
不瘦80斤不改名4 小时前
HTML基础(一)
开发语言·前端·html
UXbot4 小时前
AI画原型工具如何帮非设计师快速生成UI界面
前端·vue.js·ui·kotlin·swift·原型模式·web app
掘根4 小时前
【微服务即时通讯】登录注册界面设计
微服务·云原生·架构
前端若水4 小时前
原生嵌套(Nesting):以后还写 SCSS 吗?
前端·css·scss
xlq223224 小时前
52.TcpSocket
linux·服务器·网络
兄弟加油,别颓废了。4 小时前
系统全功能详细操作手册,从启动到测试
前端·chrome
сокол4 小时前
【网安-Web渗透测试-内网渗透】内网横向移动——IPC连接
服务器·windows·网络安全·系统安全