前端架构实战:当服务器关闭时,如何优雅提示 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)清理缓存。
    通过这种全局层面的容错处理,你的前端应用在面对后端服务波动时,将表现出更高的健壮性和专业度。
相关推荐
小程故事多_8011 分钟前
拆解SOP+ReAct对话Agent,告别硬编码,解锁智能对话的柔性迭代能力
前端·人工智能·react.js·前端框架
nicole bai14 分钟前
vue 自定义模块内容
前端·javascript·vue.js
清水白石00830 分钟前
Python 类定义阶段自动注册子类:从 `__init_subclass__` 到插件系统实战
linux·前端·python
蝶恋舞者1 小时前
DNS 服务器(后续持续更新)
运维·服务器
2601_958352901 小时前
从智能安防到矿山预警:AR1105声源定位模组的行业应用与架构解析
人工智能·嵌入式硬件·架构·机器人·回音消除·声源定位
Mortalbreeze1 小时前
深入理解 Linux 线程机制(四):线程同步——条件变量与信号量
linux·运维·服务器·开发语言·c++
用户69371750013841 小时前
Kimi K3 综合能力处于全球第一梯队
android·前端·后端
Huangjin007_2 小时前
【Linux 系统篇(一)】入门基础指令详解(一)
linux·服务器
anno2 小时前
Agent 新手 Skill 优先级指南:从第一套必装工作流,到专业能力补全
前端·后端
Liora_Yvonne2 小时前
前端请求层到底怎么封?为什么全局 axios 单例越用越难维护
前端