Axios拦截器 -- 请求拦截器和响应拦截器

Axios 拦截器时机 + 拦截器基础

前置:拦截器基础(是什么?为什么用?怎么注册?)

在讲 "拦截时机" 前,先明确拦截器核心基础 ------ 这是理解 "自动触发、触发时机" 的前提:

1. 拦截器的定义

Axios 拦截器(Interceptor)是 Axios 提供的全局钩子函数,分为「请求拦截器」和「响应拦截器」,可在 "请求发出前" 和 "响应返回后、业务代码处理前" 统一处理请求 / 响应,是 Axios 核心扩展能力。

2. 拦截器的核心价值

  • 减少重复代码:如所有请求加 token、所有响应简化数据,无需在每个请求里重复编写;
  • 统一管控流程:如全局处理加载动画、统一捕获错误(401 跳登录、500 服务器提示);
  • 灵活控制请求 / 响应:如请求前校验参数、响应后过滤无用数据。

3. 拦截器的核心注册语法

推荐「实例拦截器」(避免污染全局),核心语法如下:

javascript

javascript 复制代码
import axios from 'axios';

// 1. 创建自定义Axios实例(项目主流用法,隔离全局配置)
const service = axios.create({
  baseURL: 'https://api.example.com', // 接口基准地址
  timeout: 5000 // 请求超时时间(5秒)
});

// 2. 注册请求拦截器:请求发出前预处理
// 入参:成功回调(必须返回config,否则请求终止)、失败回调(必须返回reject)
const requestInterceptor = service.interceptors.request.use(
  (config) => {
    // 业务示例:统一给请求头加token(最常用场景)
    const token = localStorage.getItem('token');
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config; 
  },
  (error) => {
    // 请求拦截失败(如配置错误),终止流程并抛错给后续catch
    return Promise.reject(error);
  }
);

// 3. 注册响应拦截器:响应返回后、业务处理前预处理
const responseInterceptor = service.interceptors.response.use(
  (response) => {
    // 业务示例:简化响应数据,业务层直接获取data(无需写response.data)
    return response.data;
  },
  (error) => {
    // 业务示例:统一错误处理(401未授权自动跳登录)
    if (error.response?.status === 401) {
      window.location.href = '/login'; // 跳转登录页
    }
    // 响应拦截失败,抛错给业务层catch
    return Promise.reject(error);
  }
);

// 4. 移除拦截器(可选:页面销毁/无需拦截时清理)
// service.interceptors.request.eject(requestInterceptor);
// service.interceptors.response.eject(responseInterceptor);

4. 拦截器的核心特点

  • 链式执行:支持多拦截器,请求拦截器 "后注册先执行" (栈结构)、响应拦截器 "先注册先执行"(队列结构);
  • 非侵入式:不修改原始请求 / 响应逻辑,仅做 "预处理 / 后处理";
  • 可终止流程:返回 Promise.reject(error) 可直接终止请求 / 响应流程,触发后续 catch

核心结论:拦截器触发时机(与 get/then/catch 的关系)

请求拦截器 :不是 "调用axios.get()前" 执行,而是调用axios.get()后、Axios 真正发送 HTTP 请求前 执行;

响应拦截器服务端返回响应后、.then()/.catch()执行前 执行;

✅ 整体符合 "请求 / 响应被 then/catch 处理前拦截" 的定义(请求拦截:拦截即将发出的请求;响应拦截:拦截即将交给业务的响应)。


一、纠正 "get 之前执行拦截器" 的误解

易混淆点:

  • 拦截器是提前注册 (如项目初始化时),但仅调用axios.get()(发起请求)时才触发
  • 触发后先执行请求拦截器,再发送 HTTP 请求,而非 "未调用 get 就执行拦截器"。

通俗类比

  • 注册请求拦截器 = 餐厅提前制定 "接单后核对订单" 的规则;
  • 调用axios.get() = 你向餐厅下单(发起请求);
  • 请求拦截器执行 = 服务员接单后、后厨做菜前,核对订单(加调料 / 确认地址);
  • 实际发送请求 = 后厨做菜并送出;
  • 响应拦截器执行 = 菜送回餐厅后、服务员交你前,检查菜品是否合格;
  • .then()/.catch() = 你吃到菜(处理成功)或吐槽(处理失败)。

二、完整执行链路(代码)

javascript

javascript 复制代码
import axios from 'axios';

// 1. 创建自定义Axios实例(隔离全局配置,项目推荐)
const service = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000
});

// 2. 注册请求拦截器:get调用后、发请求前执行
service.interceptors.request.use(
  (config) => {
    console.log('🔴 请求拦截器执行(get调用后,发请求前)');
    // 核心业务:给所有请求加token
    const token = localStorage.getItem('token');
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config; // 必须返回配置,请求才能继续发送
  },
  (error) => {
    console.error('🔴 请求拦截器执行失败');
    return Promise.reject(error); // 终止请求,触发catch
  }
);

// 3. 注册响应拦截器:响应返回后、then/catch前执行
service.interceptors.response.use(
  (response) => {
    console.log('🟢 响应拦截器执行(响应返回后,then/catch前)');
    return response.data; // 简化数据,业务层直接用data
  },
  (error) => {
    console.error('🟢 响应拦截器执行失败');
    // 401统一处理:登录过期跳登录页
    if (error.response?.status === 401) {
      window.location.href = '/login';
      alert('登录过期,请重新登录');
    }
    return Promise.reject(error); // 抛错给业务层catch
  }
);

// 4. 调用get发起请求(触发整个拦截器+请求链路)
console.log('📌 开始调用service.get()');
service.get('/api/test', { 
  params: { id: 123 } // URL查询参数,最终拼接为?id=123
})
.then((data) => {
  // 响应拦截器简化后,直接拿到服务端返回的原始数据
  console.log('✅ then执行(响应拦截器后):', data);
})
.catch((error) => {
  // 捕获全链路错误:拦截器失败/网络错误/服务端错误等
  console.log('❌ catch执行(响应拦截器后):', error);
});

控制台输出顺序(成功场景)

📌 开始调用service.get()

🔴 请求拦截器执行(get调用后,发请求前)

// 【底层异步发送HTTP请求,等待服务端响应】

🟢 响应拦截器执行(响应返回后,then/catch前)

✅ then执行(响应拦截器后):{...} // 直接拿到简化后的data

控制台输出顺序(失败场景:401)

📌 开始调用service.get()

🔴 请求拦截器执行(get调用后,发请求前)

// 【底层发送请求,服务端返回401】

🟢 响应拦截器执行失败

❌ catch执行(响应拦截器后):Error: Request failed with status code 401

关键结论

  • 请求拦截器:axios.get() 调用后、实际 HTTP 请求发送前执行(非 "写 get 代码前");
  • 响应拦截器:服务端返回响应后、.then()/.catch() 执行前执行;
  • 两者均实现 "请求 / 响应被 then/catch 处理前拦截" 的核心目标。

三、"拦截" 的具体行为(为什么要这个时机)

1. 请求拦截器(get 调用后,发请求前)

此时 Axios 已整合请求配置(url/params/headers 等),但未发送请求,可操作:

  • ✅ 修改配置:加 token、补 baseURL、改请求方法;
  • ✅ 校验拦截:token 过期 / 参数缺失时终止请求,避免无效请求;
  • ✅ 附加逻辑:开启加载动画、记录请求日志、取消重复请求。

2. 响应拦截器(响应返回后,then/catch 前)

此时服务端已返回响应,业务代码未处理,可操作:

  • ✅ 简化数据:仅返回response.data,简化业务层代码;
  • ✅ 统一错误:401 跳登录、404 提示资源不存在、500 提示服务器错误;
  • ✅ 数据预处理:过滤无用字段、格式化日期 / 分页数据;
  • ✅ 兜底处理:网络错误 / 超时提示 "网络异常",提升体验。

四、拦截器执行时机边界表

拦截类型 触发时机 相对于axios.get()的位置 相对于.then()/.catch()的位置 核心可操作行为
请求拦截器 调用axios.get()后,实际发请求前 调用后,发请求前 远早于(请求阶段拦截) 修改配置、校验参数、开启加载动画
响应拦截器 服务端返回响应后,.then()/.catch() 调用 get 后的 "响应阶段" 直接在前面(响应交给业务前拦截) 简化数据、统一错误、关闭加载动画

五、总结:拦截器核心逻辑

  1. 注册与触发 :拦截器提前注册(实例 / 全局),调用axios.get()/post()自动触发,无需手动调用;
  2. 时机核心 :调用axios.get() → 请求拦截器 → 发送请求 → 服务端响应 → 响应拦截器 → .then()/.catch();"处理前拦截":请求拦截 = 拦截即将发出的请求,响应拦截 = 拦截即将交给业务的响应;
  3. 核心价值:实现请求 / 响应的全局统一处理,减少重复代码,提升流程管控能力。
    简单记:拦截器是 Axios 给请求加的 "前置过滤器"、给响应加的 "后置处理器",axios.get()是触发这套过滤 / 处理流程的开关。
相关推荐
程序修理员6 小时前
java+vue实现文件下载进度条
java·开发语言·vue.js
梁正雄6 小时前
10、Python面向对象编程-2
开发语言·python
Jo乔戈里6 小时前
Python复制文件到剪切板
开发语言·python
不会代码的小猴6 小时前
C++的第十一天笔记
java·前端·jvm
任子菲阳6 小时前
学Java第五十三天——IO综合练习(1)
java·开发语言·爬虫
繁华似锦respect6 小时前
单例模式出现多个单例怎么确定初始化顺序?
java·开发语言·c++·单例模式·设计模式·哈希算法·散列表
码农很忙6 小时前
让复杂AI应用构建像搭积木:Spring AI Alibaba Graph深度指南与源码拆解
开发语言·人工智能·python
风止何安啊6 小时前
递归 VS 动态规划:从 “无限套娃计算器” 到 “积木式解题神器”
前端·javascript·算法
ohyeah6 小时前
使用 Vue 3 实现大模型流式输出:从零搭建一个简易对话 Demo
前端·vue.js·openai