【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

目录

[【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦](#【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦)

[一、为什么网络错误处理一定要下沉到 Axios 层](#一、为什么网络错误处理一定要下沉到 Axios 层)

[二、Axios 拦截器 interceptors](#二、Axios 拦截器 interceptors)

1、拦截器的基础应用

2、错误分级和策略映射的设计

3、错误对象标准化

三、结语


作者:watermelo37

CSDN优质创作者、华为云云享专家、阿里云专家博主、腾讯云"创作之星"特邀作者、火山KOL、支付宝合作作者,全平台博客昵称watermelo37。

一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。


温柔地对待温柔的人,包容的三观就是最大的温柔。


【前端实战】Axios 错误处理的设计与进阶封装,实现网络层面的数据与状态解耦

有这样一句话:"在前端项目中,网络请求失败不是异常,而是常态。"真正拉开项目工程质量差距的,不是会不会用 axios,而是如何设计一套可维护、可扩展、可协作的网络错误处理体系。成熟的项目组有现成可用的axios网络封装设计,不成熟的项目组网络错误处理原始而杂乱,很多开发者在成熟的项目组开发了多年,依然不了解Axios 错误处理的设计封装,只处在知道有这个东西,而不知道如何设计的状态下。本文围绕 Axios 的拦截器机制,系统性分析可配置、可分级、可扩展的网络请求实战封装策略。

一、为什么网络错误处理一定要下沉到 Axios 层

在项目中,如果常规错误处理放在业务层,就会需要给每个 async/await 都要写一段 try-catch,同一种错误(如 token 过期)被处理 N 次,UI 提示风格难以统一,后续想要改动极其痛苦:

javascript 复制代码
// 典型的业务层污染
async function loadList() {
  try {
    const res = await getList()
    list.value = res.data
  } catch (e) {
    ElMessage.error('请求失败')
  }
}

这肯定是不可取的,应该将错误分级并合并统一处理。对于网络错误的判断逻辑、分类、兜底策略,本就应该属于请求基础设施层。

二、Axios 拦截器 interceptors

Axios 提供了两个关键拦截器,分别是请求拦截器和响应拦截器,可以用来行使不同的职责。

1、拦截器的基础应用

网络请求一般有两大类失败,其一是HTTP / 网络层错误,比如断网、请求超时、上游错误(500/502/503)等。其二是业务层错误,比如 code !== 0(响应状态码是200,但业务状态异常)、token过期、权限问题等。

javascript 复制代码
// src/utils/api.js
import axios from 'axios';
import { ElMessage } from 'element-plus'; 

// 创建 axios 实例
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  timeout: 10000,
});

// 请求拦截器(可选:添加 token 等)
request.interceptors.request.use(
  (config) => {
    // 例如:从 localStorage 获取 token 并添加到请求头
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截是集中处理错误的核心
request.interceptors.response.use(
  (response) => {
    const { code, message, data } = response.data

    if (code !== 0) {
      return Promise.reject({
        type: 'business',
        code,
        message
      })
    }

    return data
  },
  (error) => {
    const { response } = error;

    if (response) {
      // 有响应(HTTP 状态码 4xx / 5xx)
      switch (response.status) {
        case 400:
          ElMessage.error('请求参数错误');
          break;
        case 401:
          ElMessage.error('未授权,请重新登录');
          // 可跳转到登录页
          // window.location.href = '/login';
          break;
        case 403:
          ElMessage.error('拒绝访问');
          break;
        case 404:
          ElMessage.error('请求资源不存在');
          break;
        case 500:
          ElMessage.error('服务器内部错误');
          break;
        default:
          ElMessage.error(`请求失败:${response.status}`);
      }
    } else if (error.request) {
      // 请求已发出但无响应(如网络错误、超时)
      ElMessage.error('网络异常,请检查网络连接');
    } else {
      // 其他错误(如配置错误)
      ElMessage.error('请求配置错误');
    }

    return Promise.reject(error);
  }
);

export default request;

此时业务层已经做到了数据与状态的解耦,状态问题和错误信息全部在拦截器阶段处理,返回给业务调用接口位置的只有数据:

javascript 复制代码
// 在响应拦截器里面,返回的是response.data.data,所以业务层里面只会拿到数据
const data = await api.getUser()

这样业务层就不用关心 HTTP状态码和后端返回的具体结构,也不用对请求错误类型进行具体的区分了。

2、错误分级和策略映射的设计

错误的严重程度是有等级的,不应该把所有的错误都按相同的方式处理,比如401,一般情况下应该去实现用户无感刷新,请求失败再提示用户重新登陆。

只需要加上一个简单的策略映射设计:

javascript 复制代码
const errorHandlers = {
  401() {
    logout()
    router.push('/login')
  },
  403() {
    ElMessage.error('没有权限')
  },
  default(err) {
    ElMessage.error(err.message || '请求失败')
  }
}

并在拦截器中统一调度:

javascript 复制代码
function handleBusinessError(err) {
  const handler = errorHandlers[err.code] || errorHandlers.default
  handler(err)
}

这样就能根据状态码的不同,映射不同的处理方法,长期维护和拓展问题也解决了。

3、错误对象标准化

很多项目后期痛苦的根源是 error 有时候是 string,有时候是 AxiosError,有时候是后端对象,所以需要永久地将错误处理的复杂度从业务层转移到基础设置层(即Axios)。以此来实现一个架构层面的收益。

比如定义一个标准错误结构(这部分代码仅ts需要):

javascript 复制代码
interface AppError {
  type: 'network' | 'business'
  code?: number
  message: string
  raw?: any
}

然后在 Axios 层构造,举个例子:

javascript 复制代码
axios.interceptors.response.use(
  res => {
    if (res.data.code !== 0) {
      return Promise.reject({
        type: 'business',
        code: res.data.code,
        message: res.data.msg,
        raw: res
      })
    }
    return res.data.data
  },
  error => {
    return Promise.reject({
      type: 'network',
      message: '网络异常,请稍后重试',
      raw: error
    })
  }
)

那么在业务层就只需要面对一种 error 类型了,不用操心错误类型,业务代码降维:

javascript 复制代码
try {
  await api.save()
  ElMessage.success('保存成功')
} catch (err) {
  ElMessage.error(err.message)
}

三、结语

一个成熟的 Axios 错误处理体系,应该能做到错误集中处理,业务代码干净,错误分级,有明确策略,错误结构统一,方便扩展,自然接入登录、权限、数据监控等模块。**错误处理不是异常流程,而是系统设计的一部分。**做好网络层的错误处理,实现数据与状态的解耦,会让业务层开发大有裨益。

只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

其他热门文章,请关注:

极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

Web Worker:让前端飞起来的隐形引擎

测评:这B班上的值不值?在不同城市过上同等生活水平到底需要多少钱?

通过array.filter()实现数组的数据筛选、数据清洗和链式调用

DeepSeek:全栈开发者视角下的AI革命者

TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

通过MongoDB Atlas 实现语义搜索与 RAG------迈向AI的搜索机制

【前端实战】如何让用户回到上次阅读的位置?

前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题

内存泄漏------海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏

MutationObserver详解+案例------深入理解 JavaScript 中的 MutationObserver

JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

相关推荐
真正的醒悟2 小时前
AI中的网络世界
运维·服务器·网络
IT_陈寒2 小时前
JavaScript 性能优化实战:7 个让你的应用提速 50%+ 的 V8 引擎技巧
前端·人工智能·后端
不一样的少年_2 小时前
【性能监控】别只做工具人了!手把手带你写一个前端性能检测SDK
前端·javascript·监控
开发者小天2 小时前
react中使用复制的功能
前端·javascript·react.js
AI炼金师2 小时前
Chrome 中的 Claude 入门指南
前端·chrome
Web3VentureView2 小时前
Synbo与Superpool达成合作:共建链上募资早期入口
网络·金融·web3·区块链
德迅云安全—珍珍2 小时前
2025 年 Chrome 浏览器 0Day 漏洞全面分析:八大高危漏洞遭利用
前端·chrome
wanderful_2 小时前
Javascript笔记分享-流程控制(超级超级详细!!!)
javascript·笔记·流程控制·实战案例·新手友好
chen_x_x2 小时前
域格模组使用http下载到文件系统以及分段下载
网络协议·http·xcode