axios封装及全局loading实现

效果图
在这里插入图片描述

interceptors.ts

/** axios封装
 * 请求拦截、相应拦截、错误统一处理
 */
import Axios from "axios";
import { ElMessage, ElLoading } from "element-plus";
import _ from "lodash";
const axios = Axios.create({
  // baseURL: process.env.VUE_APP_URL, // url = base url + request url
  // timeout: 50000 // request timeout
});
// loading对象
let loadingInstance: { close: () => void } | null;

// 请求合并只出现一次loading
// 当前正在请求的数量
let loadingRequestCount = 0;
// post请求头
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
// request interceptor

axios.interceptors.request.use(
  (config: any) => {
    let loadingTarget = "body";
    if (config.headers.loadingTarget) {
      loadingTarget = config.headers.loadingTarget;
    }
    const isShowLoading = config.headers.isShowLoading;
    const target = document.querySelector(loadingTarget);
    if (target && isShowLoading) {
      // 请求拦截进来调用显示loading效果
      showLoading(loadingTarget);
    }
    // do something before request is sent
    if (sessionStorage.getItem("token")) {
      config.headers.Authorization =
        "Bearer " + sessionStorage.getItem("token"); // 让每个请求携带自定义 token 请根据实际情况自行修改
    }

    return config;
  },
  (error) => {
    // do something with request error
    console.log(error); // for debug
    return Promise.reject(error);
  }
);
// http response 拦截器
axios.interceptors.response.use(
  (response) => {
    setTimeout(() => {
      hideLoading();
    }, 200);
    const data = response.data;
    return data;
  },
  (err) => {
    setTimeout(() => {
      hideLoading();
    }, 200);
    // 返回状态码不为200时候的错误处理
    ElMessage({
      message: err.toString(),
      type: "error",
      duration: 5 * 1000,
    });
    return Promise.resolve(err);
  }
);

// 显示loading的函数 并且记录请求次数 ++
const showLoading = (target: any) => {
  if (loadingRequestCount === 0) {
    loadingInstance = ElLoading.service({
      lock: true,
      text: "加载中...",
      target: target,
      background: "rgba(255,255,255,0.5)",
    });
  }
  loadingRequestCount++;
};

// 隐藏loading的函数,并且记录请求次数
const hideLoading = () => {
  if (loadingRequestCount <= 0) return;
  loadingRequestCount--;
  if (loadingRequestCount === 0) {
    toHideLoading();
  }
};

// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次. 防止连续请求时, loading闪烁的问题。
const toHideLoading = _.debounce(() => {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  loadingInstance.close();
  loadingInstance = null;
}, 300);

export default axios;

request.ts

import instance from "./interceptors";
import { ElMessage } from "element-plus";

export default class baseRequest {
  private url: any;
  private params: any;

  constructor(url: any, params: any) {
    this.url = url;
    this.params = typeof params === "undefined" ? {} : params;
  }

  get(...params: any[]) {
    return instance
      .get(this.url, {
        params: this.params,
        headers: {
          loadingTarget: params[0],
          isShowLoading: params[1] === undefined ? true : params[1],
        },
      })
      .then((res: any) => {
        if (res.code === "200") {
          return Promise.resolve(res.entitys);
        } else {
          ElMessage({
            message: res.entitys[Object.keys(res.entitys)[0]],
            type: "error",
            duration: 5 * 1000,
          });
          return Promise.resolve(false);
        }
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }

  post(...params: any[]) {
    return instance
      .post(this.url, this.params, {
        headers: {
          loadingTarget: params[0],
          isShowLoading: params[1] === undefined ? true : params[1],
        },
      })
      .then((res: any) => {
        if (res.code === "200") {
          return Promise.resolve(res.entitys);
        } else {
          ElMessage({
            message: res.entitys[Object.keys(res.entitys)[0]],
            type: "error",
            duration: 5 * 1000,
          });
          Promise.resolve(false);
        }
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }

  put(...params: any[]) {
    return instance
      .put(this.url, this.params, {
        headers: {
          loadingTarget: params[0],
          isShowLoading: params[1] === undefined ? true : params[1],
        },
      })
      .then((res: any) => {
        if (res.code === "200") {
          return Promise.resolve(res.entitys);
        } else {
          ElMessage({
            message: res.entitys[Object.keys(res.entitys)[0]],
            type: "error",
            duration: 5 * 1000,
          });
          Promise.resolve(false);
        }
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }

  delete(...params: any[]) {
    return instance
      .delete(this.url, {
        params: this.params,
        headers: {
          loadingTarget: params[0],
          isShowLoading: params[1] === undefined ? true : params[1],
        },
      })
      .then((res: any) => {
        if (res.code === "200") {
          return Promise.resolve(res.entitys);
        } else {
          ElMessage({
            message: res.entitys[Object.keys(res.entitys)[0]],
            type: "error",
            duration: 5 * 1000,
          });
          Promise.resolve(false);
        }
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }

  upfile(...params: any[]) {
    return instance
      .post(this.url, this.params, {
        headers: {
          "Content-Type": "multipart/form-data",
          "X-Requested-With": "XMLHttpRequest",
          loadingTarget: params[0],
          isShowLoading: params[1] === undefined ? true : params[1],
        },
      })
      .then((res: any) => {
        if (res.code === "200") {
          return Promise.resolve(res.entitys);
        } else {
          ElMessage({
            message: res.entitys[Object.keys(res.entitys)[0]],
            type: "error",
            duration: 5 * 1000,
          });
          Promise.resolve(false);
        }
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }

  downfile(...params: any[]) {
    return instance
      .post(this.url, this.params, { responseType: "blob" })
      .then((res: any) => {
        const fileReader = new FileReader();
        fileReader.onload = function (e: any) {
          try {
            const jsonData = JSON.parse(e.target.result); // 说明是普通对象数据,后台转换失败
            if (jsonData.code) {
              ElMessage({
                message: jsonData.message,
                type: "error",
                duration: 5 * 1000,
              });
              Promise.resolve(false);
            }
          } catch (err) {
            // 解析成对象失败,说明是正常的文件流
            const url = window.URL.createObjectURL(res);
            const eleLink = document.createElement("a");
            eleLink.href = url;
            eleLink.download = params[2];
            // eleLink.download = "1.xls";
            document.body.appendChild(eleLink);
            eleLink.click();
            window.URL.revokeObjectURL(url);
          }
        };
        fileReader.readAsText(res);
      })
      .catch((e) => {
        ElMessage({
          message: e,
          type: "error",
          duration: 5 * 1000,
        });
        Promise.resolve(false);
      });
  }
}

使用
方法中可以传递三个参数,依次为,loadingTarget,isShowLoading,downloadFlileName

  • loadingTarget:默认在body上显示lodaing,可以传入html标签的id
  • isShowLoading:是否显示lodaing,默认为true,
  • downloadFlileName:文件下载名称;需要传入文件格式,如 文本.txt
import BaseRequest from "@/request/request";

const loginApi = {
  /**
   * 查询
   */
  login(params: any): any {
    const url = `/api/staff/login`;
    const BaseRequestFun = new BaseRequest(url, params);
    return BaseRequestFun.post();
  },
  /**
   * 查询菜单
   */
  queryMenuByRoleCode(rolecode: any): any {
    const url = `/api/rolepopedom/menus/${rolecode}`;
    const BaseRequestFun = new BaseRequest(url, "");
    return BaseRequestFun.get();
  },
};
export default loginApi;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值