前端架构实战:当服务器关闭时,如何优雅提示 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)清理缓存。
    通过这种全局层面的容错处理,你的前端应用在面对后端服务波动时,将表现出更高的健壮性和专业度。
相关推荐
Pedantic1 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘2 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆2 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师3 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆3 小时前
VSCode自动格式化三要素
前端
爱勇宝4 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen4 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518136 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端