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

相关推荐
消失的旧时光-19434 小时前
Kotlinx.serialization 对多态对象(sealed class )支持更好用
java·服务器·前端
少卿4 小时前
React Compiler 完全指南:自动化性能优化的未来
前端·javascript
广州华水科技4 小时前
水库变形监测推荐:2025年单北斗GNSS变形监测系统TOP5,助力基础设施安全
前端
广州华水科技4 小时前
北斗GNSS变形监测一体机在基础设施安全中的应用与优势
前端
七淮4 小时前
umi4暗黑模式设置
前端
8***B4 小时前
前端路由权限控制,动态路由生成
前端
军军3605 小时前
从图片到点阵:用JavaScript重现复古数码点阵艺术图
前端·javascript
znhy@1235 小时前
Vue基础知识(一)
前端·javascript·vue.js
terminal0075 小时前
浅谈useRef的使用和渲染机制
前端·react.js·面试
我的小月月5 小时前
🔥 手把手教你实现前端邮件预览功能
前端·vue.js