axios的二次封装(后台管理+H5活动)

50 阅读2分钟
npm install axios --save

一、针对后台管理系统

后台管理系统这边主要对切换路由取消上一次的未完成请求的情况,节约请求资源和时间。

import axios from "axios";
import { message } from "antd";
import { Storage } from "@/utils";// 本次存储的封装

// 取消请求操作
const allPendingRequestsRecord = [];
const pending = {};
const removeAllPendingRequestsRecord = () => {
  allPendingRequestsRecord &&
    allPendingRequestsRecord.forEach((func) => {
      // 取消请求(调用函数就是取消该请求)
      func("路由跳转了取消所有请求");
    });
  // 移除所有记录
  allPendingRequestsRecord.splice(0);
};

// 取消同一个重复的ajax请求
const removePending = (key, isRequest = false) => {
  if (pending[key] && isRequest) {
    pending[key]("取消重复请求");
  }
  delete pending[key];
};

// 取消所有请求的函数
export const getConfirmation = (mes = "", callback = () => {}) => {
  removeAllPendingRequestsRecord();
  callback();
};

const Service = axios.create({
  baseURL: "/api",
  timeout: 300000,
  responseType: "json",
  withCredentials: false, // 是否允许带cookie这些
  headers: {
    "Content-Type": "application/json;charset=utf-8"
  }
});

Service.interceptors.request.use(
  (config) => {
    let reqData = "";
    // 处理如url相同请求参数不同时上一个请求被屏蔽的情况
    if (config.method === "get") {
      reqData = config.url + config.method + JSON.stringify(config.params);
    } else {
      reqData = config.url + config.method + JSON.stringify(config.data);
    }
    // 如果用户连续点击某个按钮会发起多个相同的请求,可以在这里进行拦截请求并取消上一个重复的请求
    removePending(reqData, true);
    // 设置请求的 cancelToken(设置后就能中途控制取消了)
    config.cancelToken = new axios.CancelToken((c) => {
      pending[reqData] = c;
      allPendingRequestsRecord.push(c);
    });
    const tokens = Storage.get("tokens") || "";
    config.headers.tokens = tokens;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

Service.interceptors.response.use(
  (response) => {
    const resType = response.config.responseType;
    const res = response.data;
    // removePending(response.config)
    // 处理服务直接返回二进制文件情况
    // 配合下载
    if (res && response.headers["content-disposition"]) {
      const filename =
        response.headers["content-disposition"]?.split("filename=")[1];
      return {
        filename,
        blob: res
      };
    }
    switch (response.data.code) {
      case 200:
        return response;
      default:
        message.error({
          content: response.data.message,
          duration: 2
        });
        break;
    }
  },
  (error) => {
    if (axios.isCancel(error)) {
      return new Promise(() => {});
    }
    message.error({
      content: error,
      duration: 2
    });
    return Promise.reject(error);
  }
);

export default Service;

二、针对H5活动(嵌入安卓)

H5里对axios主要是对加入了全局loading的效果,请求多个接口只会出现一次loading效果。

import { Toast } from "antd-mobile";

function startLoading() {
  Toast.show({
    icon: "loading",
    duration: 0,
    position: "center",
    maskClickable: "false",
  });
}

function endLoading() {
  Toast.clear();
}

let needLoadingRequestCount = 0;

function showFullScreenLoading() {
  if (needLoadingRequestCount === 0) {
    startLoading();
  }
  needLoadingRequestCount++;
}

function tryHideFullScreenLoading() {
  if (needLoadingRequestCount <= 0) return;
  needLoadingRequestCount--;
  if (needLoadingRequestCount === 0) {
    endLoading();
  }
}

const Service = axios.create({
  // baseURL: import.meta.env.DEV ? "/api" : BASE_URL,
  baseURL: BASE_URL,
  timeout: 300000,
  responseType: "json",
  withCredentials: false, // 是否允许带cookie这些
  headers: {
    "Content-Type": "application/json;charset=utf-8",
  },
});

Service.interceptors.request.use(
  (config) => {
    showFullScreenLoading();
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

Service.interceptors.response.use(
  (response) => {
    tryHideFullScreenLoading();
    switch (response?.data?.code) {
      case 200:
        return response;
      case 404:
        window.jsInvokeAndroid?.goLogin();
        break;
      default:
        Toast.show({
          content: response.data.message,
          position: "top",
          duration: 2000,
          maskClassName: "common-toast",
        });
        return Promise.reject(response);
    }
  },
  (error) => {
    tryHideFullScreenLoading();
    return Promise.reject(error);
  }
);

//最后把封装好的axios导出
export default Service;