Axios 拦截器

Axios 拦截器是 Axios 库中非常强大的功能,它允许你在请求发送前或响应返回后对数据进行处理。下面详细介绍 Axios 拦截器的使用方法:

1. 请求拦截器

基本用法

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

// 添加请求拦截器
axios.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    console.log('请求配置:', config);
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

实际应用场景

javascript 复制代码
// 添加认证 token
axios.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 添加公共参数
axios.interceptors.request.use(
  (config) => {
    config.params = {
      ...config.params,
      timestamp: Date.now(),
      version: '1.0.0'
    };
    return config;
  }
);

2. 响应拦截器

基本用法

javascript 复制代码
// 添加响应拦截器
axios.interceptors.response.use(
  function (response) {
    // 2xx 范围内的状态码都会触发该函数
    // 对响应数据做点什么
    console.log('响应数据:', response);
    return response;
  },
  function (error) {
    // 超出 2xx 范围的状态码都会触发该函数
    // 对响应错误做点什么
    console.log('响应错误:', error);
    return Promise.reject(error);
  }
);

实际应用场景

javascript 复制代码
// 统一处理响应数据
axios.interceptors.response.use(
  (response) => {
    // 如果后端返回的数据有统一格式,可以在这里处理
    const { data, code, message } = response.data;
    
    if (code === 200) {
      return data;
    } else {
      // 业务错误
      return Promise.reject(new Error(message));
    }
  },
  (error) => {
    // 处理 HTTP 错误
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 未授权,跳转到登录页
          window.location.href = '/login';
          break;
        case 403:
          // 禁止访问
          console.error('没有权限访问该资源');
          break;
        case 500:
          // 服务器错误
          console.error('服务器内部错误');
          break;
        default:
          console.error('请求失败:', error.message);
      }
    }
    return Promise.reject(error);
  }
);

3. 完整示例

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

// 创建 axios 实例
const instance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 显示 loading
    showLoading();
    
    // 添加 token
    const token = getToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 记录请求开始时间
    config.metadata = { startTime: new Date() };
    
    return config;
  },
  (error) => {
    hideLoading();
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    // 隐藏 loading
    hideLoading();
    
    // 计算请求耗时
    const endTime = new Date();
    const duration = endTime - response.config.metadata.startTime;
    console.log(`请求 ${response.config.url} 耗时: ${duration}ms`);
    
    // 统一处理响应格式
    const { code, data, message } = response.data;
    
    if (code === 200) {
      return data;
    } else {
      // 业务逻辑错误
      showMessage(message, 'error');
      return Promise.reject(new Error(message));
    }
  },
  (error) => {
    // 隐藏 loading
    hideLoading();
    
    // 处理 HTTP 错误
    if (error.response) {
      const { status, data } = error.response;
      
      switch (status) {
        case 401:
          removeToken();
          router.push('/login');
          break;
        case 403:
          showMessage('没有权限访问该资源', 'error');
          break;
        case 500:
          showMessage('服务器内部错误', 'error');
          break;
        default:
          showMessage(data?.message || '请求失败', 'error');
      }
    } else if (error.request) {
      // 请求发送失败
      showMessage('网络连接失败,请检查网络', 'error');
    } else {
      // 其他错误
      showMessage(error.message, 'error');
    }
    
    return Promise.reject(error);
  }
);

// 辅助函数
function showLoading() {
  // 显示 loading 的逻辑
}

function hideLoading() {
  // 隐藏 loading 的逻辑
}

function showMessage(message, type) {
  // 显示消息的逻辑
}

function getToken() {
  return localStorage.getItem('token');
}

function removeToken() {
  localStorage.removeItem('token');
}

export default instance;

4. 移除拦截器

javascript 复制代码
// 添加拦截器时会返回一个 ID
const requestInterceptor = axios.interceptors.request.use(config => config);
const responseInterceptor = axios.interceptors.response.use(response => response);

// 移除拦截器
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);

5. 多个拦截器的执行顺序

javascript 复制代码
// 拦截器会按照添加顺序执行
axios.interceptors.request.use(config => {
  console.log('第一个请求拦截器');
  return config;
});

axios.interceptors.request.use(config => {
  console.log('第二个请求拦截器');
  return config;
});

axios.interceptors.response.use(response => {
  console.log('第一个响应拦截器');
  return response;
});

axios.interceptors.response.use(response => {
  console.log('第二个响应拦截器');
  return response;
});

// 执行顺序:
// 第一个请求拦截器 → 第二个请求拦截器 → 请求发送
// 第一个响应拦截器 ← 第二个响应拦截器 ← 响应返回

6. 在特定实例中使用拦截器

javascript 复制代码
// 创建不同的 axios 实例用于不同的 API
const authApi = axios.create({
  baseURL: 'https://auth.api.com'
});

const dataApi = axios.create({
  baseURL: 'https://data.api.com'
});

// 为不同实例添加不同的拦截器
authApi.interceptors.request.use(config => {
  // 认证相关的拦截逻辑
  return config;
});

dataApi.interceptors.request.use(config => {
  // 数据相关的拦截逻辑
  return config;
});

Axios 拦截器是一个非常实用的功能,可以帮助你统一处理请求和响应,减少重复代码,提高开发效率。

相关推荐
GIS学姐嘉欣17 小时前
0帧起手《Vue零基础教程》,从前端框架到GIS开发
前端·vue.js·前端框架·gis
麦麦在写代码17 小时前
前端学习6(JS 1)
前端·javascript·学习
白帽子黑客杰哥17 小时前
CTF Web题目常用考点与解题技巧合集
前端·数据库·web安全·网络安全·ctf·信息收集
许___17 小时前
axios使用 CancelToken / AbortController 方法进行取消请求
前端·javascript
LYFlied17 小时前
Webpack详细打包流程解析
前端·面试·webpack·node.js·打包·工程化
明朝百晓生17 小时前
强化学习[page14]【chapter7】Temporal-Difference Learning (TD learning)
前端·html
我只会写Bug啊17 小时前
B站/爱奇艺防录屏防截屏原理及Vue3实战实现
前端·软件开发
蜗牛攻城狮17 小时前
前端构建工具详解:Vite 与 Webpack 深度对比与实战指南
前端·webpack·vite·构建工具
IT_陈寒17 小时前
Redis 性能翻倍的 5 个冷门技巧,90%开发者都不知道的底层优化!
前端·人工智能·后端