构建健壮的 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),将错误日志发送到远程服务器,便于监控和调试。

相关推荐
多啦爱梦的梦想22 分钟前
项目中把webpack 打包改为vite 打包
前端·webpack
小刘不知道叫啥32 分钟前
简单说一下 Webpack分包
前端·javascript·webpack·node.js
Dontla36 分钟前
《黑马前端ajax+node.js+webpack+git教程》(笔记)——node.js教程+webpack教程(nodejs教程)
前端·ajax·node.js
繁依Fanyi1 小时前
项目记录:「五秒反应挑战」小游戏的开发全过程
前端·codebuddy首席试玩官
肥肠可耐的西西公主1 小时前
前端(vue)学习笔记(CLASS 6):路由进阶
前端·vue.js·学习
*小雪1 小时前
uniapp打包H5,输入网址空白情况
前端·uni-app
李梨与狸2 小时前
vue中excel文件 打包后不展示问题
前端·vue.js·excel
前端达人2 小时前
React 播客专栏 Vol.13|样式不难搞,Tailwind CSS 与 SVG 实战入门
前端·javascript·css·react.js·前端框架
xcs194052 小时前
开发 前端搭建npm v11.4.0 is known not to run on Node.js v14.18.1.
前端·npm·node.js
等等5432 小时前
CSS高级技巧
前端·css