Axios拦截器:请求与响应的处理

Axios拦截器:请求与响应的处理

_

🎯 什么是拦截器?

拦截器是Axios提供的强大功能,允许我们在请求发送到服务器之前或响应到达客户端之前对其进行拦截和处理。这为统一的错误处理、数据转换、身份验证等提供了便利。

📤 1. 请求拦截器

作用说明

请求拦截器在请求发送之前执行,主要用于:

  • 添加统一的请求头(如token认证)

  • 请求参数转换

  • 请求日志记录

  • 请求取消等

代码示例

import axios from "axios";

// 创建axios实例
const request = axios.create({
  baseURL: 'https://api.example.com', // 设置基础URL
  timeout: 10000, // 设置超时时间
});

// 请求拦截器
request.interceptors.request.use(
  (config) => { 
    // 从localStorage获取token
    const token = localStorage.getItem("token");
    
    // 如果有token,添加到请求头
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 可以添加其他通用处理
    config.headers['Content-Type'] = 'application/json';
    
    console.log("请求拦截器启动 - URL:", config.url);
    
    return config;
  },
  (error) => {
    // 请求错误处理
    console.error("请求拦截器错误:", error);
    return Promise.reject(error); // ❌修正:使用分号而不是逗号
  }
);

export default request;

常用场景示例

// 统一添加时间戳
request.interceptors.request.use(config => {
  config.params = {
    ...config.params,
    _t: Date.now() // 防止缓存
  };
  return config;
});

// 统一处理loading状态
request.interceptors.request.use(config => {
  showLoading(); // 显示loading
  return config;
});

📥 2. 响应拦截器

作用说明

响应拦截器在服务器响应到达之后、业务代码执行之前执行,主要用于:

  • 统一错误处理

  • 响应数据格式化

  • Token过期处理

  • 状态码统一处理

优化后的代码示例

import axios from "axios";

const request = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    // 2xx 范围内的状态码都会触发该函数
    console.log("响应拦截器启动 - 状态码:", response.status);
    
    // 可以在这里统一处理响应数据
    // 例如:假设后端返回的数据结构为 { code: 200, data: {...}, message: "success" }
    if (response.data.code === 200) {
      return response.data.data; // 直接返回data部分
    } else {
      // 业务错误处理
      handleBusinessError(response.data.message);
      return Promise.reject(new Error(response.data.message));
    }
  },
  (error) => {
    // 超出 2xx 范围的状态码都会触发该函数
    
    if (error.response) {
      // 服务器返回了错误状态码
      const status = error.response.status;
      
      switch (status) {
        case 401:
          // 未授权,清除token并跳转登录页
          localStorage.removeItem("token");
          window.location.href = '/login';
          break;
        case 403:
          console.error("没有权限访问");
          break;
        case 404:
          console.error("请求的资源不存在");
          break;
        case 500:
          console.error("服务器内部错误");
          break;
        default:
          console.error("请求失败:", error.response.status);
      }
    } else if (error.request) {
      // 请求已发出但没有收到响应
      console.error("网络错误,请检查网络连接");
    } else {
      // 请求配置错误
      console.error("请求配置错误:", error.message);
    }
    
    return Promise.reject(error);
  }
);

// 业务错误处理函数
function handleBusinessError(message) {
  // 可以显示错误提示、发送错误日志等
  console.error("业务错误:", message);
  // 例如:showErrorMessage(message);
}

export default request;

🔧 完整的拦截器配置示例

import axios from "axios";

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

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    // 添加token
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 添加时间戳防止缓存
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      };
    }
    
    // 显示loading
    if (config.showLoading !== false) {
      // showGlobalLoading();
    }
    
    return config;
  },
  (error) => {
    console.error("请求配置错误:", error);
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    // 隐藏loading
    // hideGlobalLoading();
    
    // 统一处理响应数据
    const { code, data, message } = response.data;
    
    if (code === 200) {
      return data;
    } else if (code === 401) {
      // token过期处理
      localStorage.removeItem("token");
      window.location.href = '/login';
      return Promise.reject(new Error("登录已过期,请重新登录"));
    } else {
      // 其他业务错误
      return Promise.reject(new Error(message || "请求失败"));
    }
  },
  (error) => {
    // 隐藏loading
    // hideGlobalLoading();
    
    // 统一错误处理
    handleError(error);
    return Promise.reject(error);
  }
);

export default request;

💡 最佳实践建议

  1. 创建独立实例:避免直接修改全局axios配置

  2. 合理设置baseURL:便于环境切换和API管理

  3. 统一的错误处理:在前端拦截器中处理通用错误

  4. token管理:在请求拦截器中统一添加认证信息

  5. 日志记录:适当添加日志便于调试

  6. 类型安全:在TypeScript项目中定义响应数据类型

📝 总结

拦截器是Axios的强大功能,通过合理使用请求和响应拦截器,我们可以:

  • 🔐 统一处理身份验证

  • 🔄 统一转换数据格式

  • 🛡️ 统一处理错误情况

  • 📊 统一添加请求参数

  • 🚮 简化业务代码

CSS界面浮现优先级 2024-06-03
解决 Git 推送/克隆时的 Permission denied (publickey) 错误 2024-01-30

评论区