前端架构实战:当服务器关闭时,如何优雅提示 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)清理缓存。
    通过这种全局层面的容错处理,你的前端应用在面对后端服务波动时,将表现出更高的健壮性和专业度。
相关推荐
充电zcx1 小时前
Linux:4:开发工具详解
linux·运维·服务器
梦帮科技1 小时前
AI 音乐产品的发布工程:验证门、数据发布、回滚与生产运维纪律
数据结构·数据库·架构·node.js·音视频·动态规划·推荐算法
西安栈上月明软件科技1 小时前
从 Linux 0.01 到 AI 开源:星图邻的开源实践
人工智能·自然语言处理·架构·开源·fastapi
泯泷1 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
野槐4 小时前
前端项目优化(有了我,会发生...)
前端
Lynne3094 小时前
工业网络,到底该集中还是自治?
网络·架构·数据
aa小小5 小时前
【无标题】
前端
计算机魔术师6 小时前
还在单线程跟 AI 聊天?Claude Code 并行多会话让你一个人干三个人的活
前端
志尊宝6 小时前
Vue3 零基础每日笔记(038):亲手封装 useDebounceFn 与 useThrottleFn——高频事件的流量阀
前端·javascript·vue·html·vue3
JavaGuide6 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端