构建健壮的 Axios 请求管理器:提升 React 应用的 API 交互体验

创建自定义 Axios 实例

引入依赖

首先,我们需要安装 axios 和其他辅助库:

bash 复制代码
npm install axios qs nprogress antd-mobile
  • axios:用于发起 HTTP 请求。
  • qs :用于序列化复杂的查询参数,支持点号表示法(如 user.name)。
  • nprogress:用于显示加载进度条,提升用户体验。
  • antd-mobile:提供一些常用的 UI 组件,如 Toast 提示框。

配置 Axios 实例

接下来,我们创建一个自定义的 Axios 实例,并为其配置一些全局选项。这些选项包括 baseURLtimeoutheaders 等。

js 复制代码
import axios from "axios";
import qs from "qs";
import { Toast } from "antd-mobile";
import NProgress from "nprogress"; // 引入nprogress插件
import "nprogress/nprogress.css"; // 这个nprogress样式必须引入

// 配置新建一个 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_PATH, // 从环境变量中获取 API 基础路径
  timeout: 90000, // 设置请求超时时间为 90 秒
  headers: {
    "Content-Type": "application/json", // 默认请求头
    Accept: "*/*",
  },
  paramsSerializer: {
    serialize(params) {
      return qs.stringify(params, { allowDots: true }); // 支持点号表示法
    },
  },
});
baseURL

baseURL 是 API 的基础路径,通常是从环境变量中获取的。这样做可以方便地在不同环境下切换 API 地址(如开发环境、测试环境、生产环境)。你可以通过 .env 文件来配置不同的环境变量。

例如,在 .env.development 中:

bash 复制代码
VITE_API_PATH=http://localhost:3000/api

.env.production 中:

bash 复制代码
VITE_API_PATH=https://api.example.com/v1
timeout

timeout 设置了请求的最大等待时间。如果请求在指定时间内没有完成,axios 会自动取消请求并抛出一个超时错误。根据业务需求,你可以调整这个值。对于上传文件或大数据传输的场景,建议设置较长的超时时间。

headers`

headers 用于设置请求的默认头部信息。在这里,我们设置了 Content-Typeapplication/json,并允许接受任何类型的响应(Accept: "*/*")。你还可以根据需要添加其他头部信息,例如认证令牌。

paramsSerializer`

paramsSerializer 用于序列化查询参数。默认情况下,axios 使用 qs 库来序列化对象为 URL 查询字符串。我们通过 allowDots: true 允许使用点号表示法(如 user.name),这在某些 API 中非常有用。


添加请求拦截器

请求拦截器允许我们在请求发送之前对请求进行预处理。常见的应用场景包括:

  • 添加认证令牌 :如果用户已经登录,可以在请求头中添加 Authorization 字段。
  • 显示加载进度条 :使用 NProgress 插件显示加载进度条,提升用户体验。
  • 日志记录:记录请求的 URL、方法和参数,便于调试。
js 复制代码
// 添加请求拦截器
service.interceptors.request.use(
  (config) => {
    NProgress.start(); // 设置加载进度条(开始..)

    // 获取 token 并添加到请求头
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // 打印请求日志(可选)
    console.log("Request:", config);

    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);
认证令牌

在大多数情况下,API 需要验证用户的身份。我们可以通过 localStoragesessionStorage 存储用户的认证令牌,并在每次请求时将其添加到 Authorization 头部。注意,这里我们使用了 Bearer 方式传递令牌,这是 OAuth 2.0 标准中的常见做法。

加载进度条

NProgress 是一个轻量级的加载进度条插件,它可以很好地与 axios 拦截器结合使用。当请求开始时,调用 NProgress.start() 显示进度条;当请求结束时,调用 NProgress.done() 隐藏进度条。这样可以给用户一种"正在加载"的视觉反馈,提升用户体验。

日志记录

在开发阶段,打印请求日志可以帮助我们快速定位问题。你可以选择在 console.log 中输出请求的 URL、方法、参数等信息。当然,为了不影响生产环境的性能,建议在生产环境中关闭日志记录。


添加响应拦截器

响应拦截器允许我们在接收到响应之后对响应进行处理。常见的应用场景包括:

  • 统一错误处理:捕获所有 API 错误,并根据错误类型显示相应的提示信息。
  • 隐藏加载进度条:当响应返回时,隐藏加载进度条。
  • 处理未授权访问:如果用户被登出或令牌过期,重定向到登录页面。
js 复制代码
// 添加响应拦截器
service.interceptors.response.use(
  (response) => {
    const res = response.data;
    NProgress.done(); // 设置加载进度条(结束..)

    // 打印响应日志(可选)
    console.log("Response:", res);

    // 检查响应状态码
    if (
      res.code * 1 !== 200 &&
      res.status * 1 !== 200 &&
      res.status * 1 !== 1
    ) {
      // 如果状态码不是 200 或 1,显示错误提示
      return Toast.show({
        content: res.message || res.msg,
        position: "bottom",
      });
    }

    return res;
  },
  (error) => {
    let errorMessage = "";

    // 处理不同的错误类型
    if (error.message.includes("timeout")) {
      errorMessage = "网络超时";
    } else if (error.message === "Network Error") {
      errorMessage = "网络连接错误";
    } else if (error.response) {
      errorMessage = error.response.statusText || "未知错误";
    } else {
      errorMessage = "接口路径找不到";
    }

    // 显示错误提示
    Toast.show({
      icon: "fail",
      content: errorMessage,
      position: "bottom",
    });

    return Promise.reject(error);
  }
);
统一错误处理

在响应拦截器中,我们首先检查响应的状态码。如果状态码不是 2001,则认为请求失败,并使用 Toast 组件显示错误提示。Toastantd-mobile 提供的一个轻量级提示框组件,适合用于展示短暂的消息。

隐藏加载进度条

无论请求成功还是失败,我们都应该在响应返回时调用 NProgress.done() 来隐藏加载进度条。这样可以确保进度条不会一直显示,影响用户体验。

处理未授权访问

如果后端返回的响应中包含特定的状态码(如 401102),我们可以判断用户是否被登出或令牌过期。在这种情况下,我们可以清除本地存储中的令牌,并重定向用户到登录页面。虽然在这个例子中没有实现,但你可以根据业务需求添加类似的逻辑。

自定义错误提示

我们根据不同的错误类型(如超时、网络错误、接口路径找不到等)生成相应的错误提示信息。通过 Toast 组件显示这些提示,用户可以清楚地了解发生了什么问题,并采取相应的行动。


导出 Axios 实例

最后,我们将自定义的 Axios 实例导出,以便在其他模块中使用。

js 复制代码
// 导出 axios 实例
export default service;

使用自定义 Axios 实例

现在,我们可以在项目的其他地方使用这个自定义的 Axios 实例来发起 API 请求。例如,在一个组件中发起 GET 请求:

js 复制代码
import service from "@/utils/request";

// 发起 GET 请求
service.get("/users").then((res) => {
  console.log("Users:", res);
}).catch((error) => {
  console.error("Error:", error);
});

或者发起 POST 请求:

js 复制代码
import service from "@/utils/request";

// 发起 POST 请求
service.post("/login", {
  username: "admin",
  password: "123456",
}).then((res) => {
  console.log("Login success:", res);
}).catch((error) => {
  console.error("Login failed:", error);
});

未来扩展

  • 缓存机制:为某些 API 请求添加缓存机制,减少不必要的网络请求。
  • 重试机制:为失败的请求添加自动重试功能,尤其是在网络不稳定的情况下。
  • 日志记录 :集成日志记录工具(如 Sentry),将错误日志发送到远程服务器,便于监控和调试。

相关推荐
热爱编程的小曾2 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin13 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox26 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼1 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_593758102 小时前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox