HOW - Axios 拦截器特性

发布于:2025-04-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

Axios 介绍

Axios 是基于 XMLHttpRequest(XHR)Promise 进行封装的 HTTP 客户端。

它的核心实现依赖于以下技术:

  1. XMLHttpRequest(XHR)

    • 在浏览器环境下,Axios 使用 XMLHttpRequest 发送 HTTP 请求,并基于它进行封装,提供更简洁的 API 和更好的错误处理机制。
    • 例如,它支持请求和响应的拦截器、超时设置、请求取消等功能,而这些都需要额外的封装才能在 XMLHttpRequest 中实现。
  2. Node.js 的 http 模块

    • 在 Node.js 环境下,Axios 使用 httphttps 模块代替 XMLHttpRequest 发送 HTTP 请求,从而实现跨环境的兼容性。
  3. Promise

    • Axios 的 API 是基于 Promise 设计的,所有请求都会返回一个 Promise,支持 async/await,比传统的 XMLHttpRequest 更加方便。
  4. 拦截器(Interceptors)

    • 通过 requestresponse 拦截器,Axios 允许在请求或响应到达应用程序之前,对其进行修改,比如添加请求头、处理错误、全局 loading 等。
  5. 取消请求(Cancel Token)

    • 依赖 AbortController 或者 CancelToken(Axios 0.x 版本提供),可以在特定条件下取消未完成的 HTTP 请求。
  6. 自动 JSON 解析

    • Axios 默认会将 JSON 响应数据自动解析成 JavaScript 对象,而 XMLHttpRequest 需要手动解析。
  7. 并发请求管理

    • 通过 axios.all()axios.spread(),支持并行发送多个请求,并在所有请求完成后进行处理。

总结来说,Axios 的底层实现主要基于 XMLHttpRequest(浏览器端)或 Node.js http 模块(服务端),同时结合 Promise、拦截器、取消请求等高级特性,提供了比原生 API 更易用的 HTTP 请求功能。

拦截器特性

Axios 拦截器(Interceptors)可以在请求发送前或响应返回后进行处理,常用于全局请求配置、错误处理、权限校验、自动重试等场景。以下是几个实际应用示例:

1. 统一添加 Token(请求拦截器)

场景:
需要在所有请求的 headers 中添加 Authorization 头部,例如 JWT Token。

import axios from "axios";

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

// 请求拦截器
api.interceptors.request.use(
  config => {
    const token = localStorage.getItem("token"); // 从本地存储获取 token
    if (token) {
      config.headers.Authorization = `Bearer ${token}`; // 设置 Authorization 头部
    }
    return config;
  },
  error => Promise.reject(error)
);

// 使用 axios 实例
api.get("/user/profile").then(response => console.log(response.data));

📌 效果:

  • 所有请求都会自动附带 Authorization 头部,避免手动在每个请求中添加。

2. 处理 401 未授权(响应拦截器)

场景:
当后端返回 401 Unauthorized,表示 Token 失效,应该自动跳转到登录页。

api.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) {
      console.error("身份认证失败,跳转到登录页...");
      window.location.href = "/login"; // 重定向到登录页面
    }
    return Promise.reject(error);
  }
);

📌 效果:

  • 如果请求返回 401,用户会被自动跳转到登录页,而不会继续执行后续逻辑。

3. 统一处理错误信息(响应拦截器)

场景:
后端返回错误时,拦截器可以解析 error.response.data,并弹出错误提示。

import { message } from "antd"; // 适用于 Ant Design 的 message 组件

api.interceptors.response.use(
  response => response,
  error => {
    if (error.response) {
      const { status, data } = error.response;
      const errorMsg = data.message || "服务器错误";
      message.error(`请求失败 (${status}): ${errorMsg}`);
    } else {
      message.error("网络异常,请检查你的连接");
    }
    return Promise.reject(error);
  }
);

📌 效果:

  • 400、500 等错误时,自动弹出友好的错误提示。

4. 请求 Loading 状态管理

场景:
在请求发起时显示 Loading 状态,请求结束后自动隐藏。

import { message } from "antd";

let requestCount = 0;

function showLoading() {
  if (requestCount === 0) {
    message.loading("加载中...", 0);
  }
  requestCount++;
}

function hideLoading() {
  requestCount--;
  if (requestCount === 0) {
    message.destroy(); // 关闭 loading
  }
}

// 请求拦截器:增加 Loading
api.interceptors.request.use(config => {
  showLoading();
  return config;
});

// 响应拦截器:移除 Loading
api.interceptors.response.use(
  response => {
    hideLoading();
    return response;
  },
  error => {
    hideLoading();
    return Promise.reject(error);
  }
);

📌 效果:

  • 多个请求时,只显示一个 Loading,所有请求完成后才关闭。

5. 自动重试请求(如 429 过载)

场景:
如果服务器返回 429 Too Many Requests,可以实现自动重试,避免短时间内请求失败。

api.interceptors.response.use(
  response => response,
  async error => {
    const { response, config } = error;
    if (response?.status === 429 && !config.__isRetryRequest) {
      config.__isRetryRequest = true;
      console.warn("请求过载,2 秒后重试...");
      await new Promise(resolve => setTimeout(resolve, 2000));
      return api(config); // 重新请求
    }
    return Promise.reject(error);
  }
);

📌 效果:

  • 如果服务器返回 429,拦截器会等待 2 秒后自动重试一次。

6. 数据格式转换(响应拦截器)

场景:
后端返回的数据格式不符合前端要求,需要在拦截器中转换。

api.interceptors.response.use(response => {
  if (response.data && response.data.result) {
    return response.data.result; // 提取需要的 `result` 数据
  }
  return response.data;
});

📌 效果:

  • 假设后端返回 { success: true, result: { name: "Tom" } },前端直接拿到 { name: "Tom" }

7. 记录请求日志(请求拦截器 + 响应拦截器)

场景:
在开发模式下,打印请求和响应日志,方便调试。

api.interceptors.request.use(config => {
  console.log("🚀 请求:", config.method?.toUpperCase(), config.url, config.data);
  return config;
});

api.interceptors.response.use(
  response => {
    console.log("✅ 响应:", response.config.url, response.data);
    return response;
  },
  error => {
    console.error("❌ 请求失败:", error.config?.url, error.response?.status);
    return Promise.reject(error);
  }
);

📌 效果:

  • 在开发者工具控制台中,能看到请求和响应的日志信息,方便调试。

总结

拦截器类型 应用场景 **示例代码
请求拦截器 统一添加 Token config.headers.Authorization = Bearer ${token}
请求拦截器 全局 Loading 处理 showLoading()hideLoading()
响应拦截器 处理 401 未授权 if (error.response.status === 401) { window.location.href = "/login"; }
响应拦截器 统一错误提示 message.error(error.response.data.message);
响应拦截器 处理 429 过载自动重试 await new Promise(resolve => setTimeout(resolve, 2000)); return api(config);
响应拦截器 数据格式转换 return response.data.result;
拦截器 请求 & 响应日志 console.log("🚀 请求:", config)

结论

Axios 拦截器非常强大,能帮助我们在全局范围内 统一管理请求和响应,减少重复代码,提升可维护性。实际项目中,可以根据需求选择合适的拦截器组合,提升开发效率!