Skip to content

封装axios和loading组件

安装

bash
npm install antd -S
npm install axios -S

代码说明

  • 通过 axios 提供的请求拦截和响应拦截的接口,控制 loading 的显示或者隐藏。在此我还设置了没有网络和网络超时的提示信息

  • 采用 DOM 来实现 loading 效果,message 组件来进行消息提示

  • 定义变量 requestCount 作为计数器,确保同一时刻如果有多个请求的话,不会同时添加多个 loading,而是只有 1 个,并在所有请求结束后才会隐藏 loading。

  • 默认所有请求都会自动有 loading 效果。如果某个请求不需要 loading 效果,可以在请求 headers 中设置 isLoading 为 false。

步骤

封装request.ts

ts
import axios, { type AxiosRequestConfig } from "axios";
import { message } from "antd";

const Axios = axios.create({
  // baseURL: import.meta.env.VITE_BASE_URL, // 设置请求的 base url
  timeout: 20000, // 设置超时时长
});

// 设置 post 请求头
Axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded;charset=UTF-8";

// 当前正在请求的数量
let requestCount = 0;

// 显示 loading(纯 DOM,不渲染 React 组件,避免 .tsx / Fast Refresh 限制)
function showLoading() {
  if (requestCount === 0 && !document.getElementById("global-loading")) {
    const dom = document.createElement("div");
    dom.id = "global-loading";
    dom.style.cssText =
      "position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(24,39,39,.2);z-index:9999;";
    dom.innerHTML =
      '<div style="font-size:14px;color:#1677ff;">加载中...</div>';
    document.body.appendChild(dom);
  }
  requestCount++;
}

// 隐藏 loading
function hideLoading() {
  requestCount--;
  if (requestCount <= 0) {
    requestCount = 0;
    document.getElementById("global-loading")?.remove();
  }
}

// 请求前拦截
Axios.interceptors.request.use(
  (config) => {
    // requestCount 为 0 才创建 loading,避免重复创建
    if (config.headers.isLoading !== false) {
      showLoading();
    }
    return config;
  },
  (err) => {
    if (err.config?.headers?.isLoading !== false) {
      hideLoading();
    }
    return Promise.reject(err);
  },
);

// 返回后拦截
Axios.interceptors.response.use(
  (res) => {
    if (res.config.headers.isLoading !== false) {
      // hideLoading();
    }
    return res;
  },
  (err) => {
    if (err.config?.headers?.isLoading !== false) {
      // hideLoading();
    }
    if (err.message === "Network Error") {
      message.warning("网络连接异常!");
    }
    if (err.code === "ECONNABORTED") {
      message.warning("请求超时,请重试");
    }
    return Promise.reject(err);
  },
);

// GET 请求
export function get<T = unknown>(
  url: string,
  params?: object,
  config?: AxiosRequestConfig,
) {
  return Axios.get<T>(url, { params, ...config }).then((res) => res.data);
}

// POST 请求
export function post<T = unknown>(
  url: string,
  data?: object,
  config?: AxiosRequestConfig,
) {
  return Axios.post<T>(url, data, config).then((res) => res.data);
}

export default Axios;

页面里面使用

tsx
import { get } from "@/api/request";
import { useEffect } from "react";
function HomePage() {
  useEffect(() => {
    get("https://httpbin.org/delay/6").then((res) => console.log(res));
  }, []);
  return (
    <div>
      <h1>Home Page</h1>
    </div>
  );
}

export default HomePage;