当前位置: 首页 > java >正文

Axios拦截器:前端通信的交通警察[特殊字符]

文章目录

  • Axios拦截器:前端通信的"交通警察"🚦
    • 引言:为什么需要拦截器?
    • 拦截器的作用与好处
      • 作用概览表
      • 五大核心好处
    • 拦截器的工作原理
      • 流程图解
      • 原理详解
    • 拦截器的多种写法与实践
      • 1. 基础写法
      • 2. 类封装写法(更工程化)
      • 3. 多实例不同拦截策略
    • 高级应用场景
      • 1. 重试机制
      • 2. 请求取消
      • 3. 性能监控
    • 拦截器最佳实践
      • 1. 组织架构建议
      • 2. 代码示例:模块化拦截器
      • 3. 注意事项
    • 总结:拦截器的核心价值

在这里插入图片描述

Axios拦截器:前端通信的"交通警察"🚦

引言:为什么需要拦截器?

想象一下你是一个城市的交通管理员,每天有成千上万的车辆(HTTP请求)在城市(你的应用)中穿梭。如果没有交通信号灯和交警(拦截器),这些车辆会乱成一团:

  • 每辆车都要自己找路(每个请求手动处理)
  • 遇到事故(错误)没有统一处理
  • 特殊车辆(特殊请求)没有优先通道

Axios拦截器就像是这个城市的智能交通管理系统,它能:

  1. 统一管理所有进出的请求和响应
  2. 自动处理重复性工作(如添加token)
  3. 集中处理错误和异常
  4. 监控和记录请求过程

拦截器的作用与好处

作用概览表

拦截器类型主要作用典型应用场景
请求拦截器在请求发送前处理添加认证token、设置请求头、参数加密
响应拦截器在响应返回后处理统一错误处理、数据格式化、响应解密

五大核心好处

  1. 代码复用:避免在每个请求中重复相同代码
  2. 集中管理:统一处理认证、错误等逻辑
  3. 流程控制:可以中断或修改请求/响应流程
  4. 增强可读性:业务代码更专注于业务本身
  5. 便于维护:修改拦截逻辑只需改一处

拦截器的工作原理

流程图解

[发起请求] → 
[请求拦截器] → 
[实际发送请求] → 
[服务器处理] → 
[响应返回] → 
[响应拦截器] → 
[最终数据处理]

原理详解

Axios内部维护了两个拦截器链(数组):

  1. 请求拦截器链:按添加顺序执行(先添加先执行)
  2. 响应拦截器链:按添加逆序执行(先添加后执行)

当发起请求时,Axios会:

  1. 创建一个Promise链
  2. 依次执行请求拦截器
  3. 发送实际HTTP请求
  4. 依次执行响应拦截器
  5. 返回最终处理结果

拦截器的多种写法与实践

1. 基础写法

// 添加请求拦截器
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么console.log('请求拦截器 - 处理请求配置', config);config.headers.Authorization = 'Bearer your_token'; // 添加tokenreturn config; // 必须返回处理后的config}, function (error) {// 对请求错误做些什么console.log('请求拦截器 - 错误处理', error);return Promise.reject(error);}
);// 添加响应拦截器
axios.interceptors.response.use(function (response) {// 对响应数据做点什么 (2xx范围内的状态码)console.log('响应拦截器 - 处理成功响应', response);return response.data; // 通常我们只需要data部分}, function (error) {// 对响应错误做点什么 (超出2xx范围的状态码)console.log('响应拦截器 - 处理错误响应', error);if (error.response.status === 401) {// 处理未授权错误window.location.href = '/login';}return Promise.reject(error);}
);

2. 类封装写法(更工程化)

class HttpInterceptor {constructor() {this.instance = axios.create({baseURL: 'https://api.example.com',timeout: 10000});this.setupInterceptors();}setupInterceptors() {// 请求拦截this.instance.interceptors.request.use(config => {// 请求前添加loadingthis.showLoading();// 添加认证信息const token = localStorage.getItem('token');if (token) {config.headers.Authorization = `Bearer ${token}`;}return config;},error => {this.hideLoading();return Promise.reject(error);});// 响应拦截this.instance.interceptors.response.use(response => {this.hideLoading();// 处理成功响应if (response.data.code === 200) {return response.data.data;} else {// 业务逻辑错误this.handleBusinessError(response.data);return Promise.reject(response.data);}},error => {this.hideLoading();// 处理HTTP错误this.handleHttpError(error);return Promise.reject(error);});}showLoading() { /* 显示加载动画 */ }hideLoading() { /* 隐藏加载动画 */ }handleBusinessError(data) {const errorMap = {401: '未授权,请重新登录',403: '拒绝访问',404: '请求资源不存在',500: '服务器错误'};const message = errorMap[data.code] || '未知错误';alert(message);}handleHttpError(error) {if (error.response) {// 服务器返回了响应但状态码不在2xx范围console.error('响应错误:', error.response.status);} else if (error.request) {// 请求已发出但没有收到响应console.error('无响应:', error.request);} else {// 发送请求时出了点问题console.error('请求错误:', error.message);}}
}// 使用示例
const http = new HttpInterceptor();
http.instance.get('/user/123');

3. 多实例不同拦截策略

// 创建两个不同的axios实例
const publicApi = axios.create({baseURL: 'https://api.example.com/public'
});const privateApi = axios.create({baseURL: 'https://api.example.com/private'
});// 公共API拦截器 - 简单处理
publicApi.interceptors.response.use(response => response.data,error => {console.error('公共API错误:', error);return Promise.reject(error);}
);// 私有API拦截器 - 复杂处理
privateApi.interceptors.request.use(config => {const token = localStorage.getItem('token');if (!token) {throw new Error('无访问令牌');}config.headers.Authorization = `Bearer ${token}`;return config;
});privateApi.interceptors.response.use(response => response.data,error => {if (error.response.status === 401) {// token过期,跳转登录window.location.href = '/login?expired=1';}return Promise.reject(error);}
);

高级应用场景

1. 重试机制

axios.interceptors.response.use(response => response,error => {const config = error.config;// 设置重试次数,默认为0config.__retryCount = config.__retryCount || 0;// 检查是否超过最大重试次数(3次)if (config.__retryCount >= 3) {return Promise.reject(error);}// 增加重试计数器config.__retryCount += 1;// 创建新的Promise来处理指数退避const delay = new Promise(resolve => {setTimeout(() => resolve(), 1000 * config.__retryCount);});// 返回Promise,在延迟后重试请求return delay.then(() => axios(config));}
);

2. 请求取消

// 创建一个Map来存储请求标识和取消函数
const pendingRequests = new Map();// 生成请求标识
const generateReqKey = (config) => {const { method, url, params, data } = config;return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&');
};// 请求拦截器 - 添加取消逻辑
axios.interceptors.request.use(config => {const requestKey = generateReqKey(config);if (pendingRequests.has(requestKey)) {// 如果请求已存在,取消前一个pendingRequests.get(requestKey).cancel('重复请求');}// 创建取消令牌config.cancelToken = new axios.CancelToken(cancel => {pendingRequests.set(requestKey, { cancel });});return config;
});// 响应拦截器 - 移除已完成请求
axios.interceptors.response.use(response => {const requestKey = generateReqKey(response.config);pendingRequests.delete(requestKey);return response;
}, error => {if (axios.isCancel(error)) {console.log('请求被取消:', error.message);return Promise.reject(error);}const requestKey = generateReqKey(error.config);if (error.config) {pendingRequests.delete(requestKey);}return Promise.reject(error);
});

3. 性能监控

// 请求开始时间记录
axios.interceptors.request.use(config => {config.metadata = { startTime: new Date() };return config;
});// 响应时间计算
axios.interceptors.response.use(response => {const endTime = new Date();const duration = endTime - response.config.metadata.startTime;console.log(`请求 ${response.config.url} 耗时 ${duration}ms`);// 可以上报到性能监控系统reportPerformance({url: response.config.url,method: response.config.method,duration: duration,status: response.status});return response;},error => {if (error.config) {const endTime = new Date();const duration = endTime - error.config.metadata.startTime;console.error(`请求 ${error.config.url} 失败,耗时 ${duration}ms`);reportPerformance({url: error.config.url,method: error.config.method,duration: duration,status: error.response?.status || 0,error: error.message});}return Promise.reject(error);}
);

拦截器最佳实践

1. 组织架构建议

/src/apiinterceptors/request/auth.js       # 认证处理loading.js    # 加载状态log.js        # 请求日志response/error.js      # 错误处理format.js     # 数据格式化index.js        # 整合所有拦截器services/         # 各个API模块http.js           # axios实例创建

2. 代码示例:模块化拦截器

// http.js - 创建axios实例
import axios from 'axios';const http = axios.create({baseURL: process.env.VUE_APP_API_BASE_URL,timeout: 30000
});export default http;// interceptors/request/auth.js
export default function addAuthToken(config) {const token = localStorage.getItem('token');if (token) {config.headers.Authorization = `Bearer ${token}`;}return config;
}// interceptors/response/error.js
export default function handleError(error) {if (error.response) {switch (error.response.status) {case 400:console.error('请求错误');break;case 401:console.error('未授权,请重新登录');break;case 403:console.error('拒绝访问');break;case 404:console.error('请求资源不存在');break;case 500:console.error('服务器错误');break;default:console.error(`未知错误: ${error.response.status}`);}}return Promise.reject(error);
}// interceptors/index.js - 整合拦截器
import http from '../../http';
import addAuthToken from './request/auth';
import handleError from './response/error';// 请求拦截器
http.interceptors.request.use(addAuthToken);// 响应拦截器
http.interceptors.response.use(response => response.data, // 直接返回datahandleError
);export default http;

3. 注意事项

  1. 执行顺序:多个拦截器按添加顺序执行

    • 请求拦截器:先添加的先执行
    • 响应拦截器:先添加的后执行
  2. 错误处理:确保拦截器中错误被正确传递

    • 使用Promise.reject传递错误
    • 不要"吞掉"错误
  3. 内存泄漏

    • 使用eject移除不再需要的拦截器
    const interceptor = axios.interceptors.request.use(...);
    axios.interceptors.request.eject(interceptor);
    
  4. 避免副作用

    • 不要在一个拦截器中修改另一个拦截器的行为
    • 保持拦截器职责单一
  5. 性能考虑

    • 拦截器中的逻辑应尽量轻量
    • 避免在拦截器中执行耗时操作

总结:拦截器的核心价值

Axios拦截器就像是你应用HTTP通信的"中间件管道",它提供了统一的入口和出口来处理所有请求和响应。通过合理使用拦截器,你可以:

  1. 标准化:统一处理认证、错误、loading状态等
  2. 解耦:将基础设施逻辑与业务逻辑分离
  3. 增强:添加重试、缓存、监控等高级功能
  4. 简化:减少业务代码中的重复逻辑

记住,强大的能力伴随着责任,拦截器虽然强大,但也需要合理设计和使用,避免过度复杂化你的请求处理流程。

http://www.xdnf.cn/news/19595.html

相关文章:

  • 搭载AX650N高能效比智能视觉芯片——AX2050系列边缘计算盒,可应用在智慧安防交通仓储教育,人脸识别,明厨亮灶,安全生产,智能机器人等
  • table表格字段明细展示
  • 不透明指针
  • 【iOS】折叠cell
  • 《青衣剑客 · Claude》连载
  • 总线矩阵的原理
  • 如何将多个Excel报表合并为一个汇总文件?
  • N32G43x Bootloader 中 ENV 区的管理与实现
  • 前缀和(优化算法)
  • ClickHouse常见问题——ClickHouseKeeper配置listen_host后不生效
  • 面试 TOP101 动态规划专题题解汇总Java版(BM62 —— BM82)
  • 二、SVN基础命令速查表
  • leetcode 1792. 最大平均通过率 中等
  • 通过 select into outfile / load data infile 进行数据导入导出学习笔记
  • 开源项目_金融分析工具TradingAgents
  • 01数据结构-红黑树
  • python 数据类型【python进阶一】
  • java设计模式一、单例模式
  • 【K8s】整体认识K8s之Configmap、Secret/ResourceQuota资源配额/访问控制
  • Linux应用开发-windows,linux环境下相关工具
  • Adobe Illustrator 2025最新破解教程下载安装教程,Illustrator2025最新版下载
  • AI 安全与伦理:当大模型拥有 “决策能力”,我们该如何建立技术边界与监管框架?
  • 新手向:前端开发中的常见问题
  • NLP大语言模型数据准备
  • 基于 DNA 的原核生物与微小真核生物分类学:分子革命下的范式重构​
  • Shell编程(二):正则表达式
  • FastK v1.1 安装与使用-生信工具59
  • Gradle vs. Maven,Java 构建工具该用哪个?
  • 喜讯!华清远见参与制定的《电子产品印制电路板可制造性设计(DFM)和可靠性设计规范》正式发布
  • 【无标题】训练、推理适用的数据类型