封装axios实例,实现Web和移动端请求完成前loading并在后端报错时展示

37 阅读2分钟

效果

请求完成前loading

web端 image.png

移动端(uniapp开发)

app-load.png

展示后端的报错信息

image.png

Web

import { useUserStore } from "@/store/user";
import axios from "axios";
import { ElLoading, ElMessage } from "element-plus";

const instance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
});

let requestCount = 0; ///记录请求次数
let loading = null;
/**
 * @function loading启动器
 */
function startLoading() {
  loading = ElLoading.service({
    lock: true,
  });
}
/**
 * @function 启动loading
 */
function openLoading() {
  if (requestCount === 0) {
    startLoading();
  }
  requestCount++; ///每有一个配置了loading:true的请求开启,count++
}
/**
 * @function loading结束器
 */
function endLoading() {
  //延迟200ms,防止太快
  setTimeout(() => {
    if (loading) {
      loading.close(); //! 所有的请求共用一个loading实例,一个关则全关
    }
  }, 200);
}
/**
 * @function 关闭loading
 */
function closeLoading() {
  if (requestCount <= 0) return;
  requestCount--; ///每有一个配置了loading:true的请求结束,count--
  if (requestCount === 0) {
    endLoading(); /// 所有请求结束,关loading
  }
}
/**
 * @function 添加请求拦截器
 */
instance.interceptors.request.use(
  (config) => {
    if (config.loading) {
      openLoading(); /// 实际使用举例:getData({},{loading:true,message:true})
    }
    const userStore = useUserStore();
    const token = userStore.token;
    if (token) {
      config.headers["Authorization"] = token;
    }
    return config;
  },
  (error) => {}
);

/**
 * @function 添加响应拦截器
 */
instance.interceptors.response.use(
  (response) => {
    const { config, data } = response;
    if (config.message) {
      const { success, message, msg } = data;
      if (success) {
        /// 可以自定义统一的成功提示,也可以每种情况自定义,我是每种自定义这里就没写
      } else {
        message && ElMessage.error(message);
        msg && ElMessage.error(msg);
      }
    }
    if (config.loading) {
      closeLoading(); /// 请求完,count--
    }
    return response;
  },
  (error) => {
    const response = error?.response;
    if (response) {
      const { status } = response;
      switch (status) {
        case 401:
          const userStore = useUserStore();
          userStore.setToken();
          userStore.setUserInfo();
          window.location.reload();
          break;
        default:
          break;
      }
    }
    const config = error?.config;
    if (config?.loading) {
      closeLoading(); /// 请求完,count--
    }
    return error;
  }
);

export default instance;

移动端(Uniapp开发)

因项目不复杂,这里做了些简化

import { useUserStore } from "@/store/user.js";
import axios from "axios";

const instance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
});

let isLoading;
function startLoading() {
  isLoading = uni.showLoading({
    title: "加载中",
    mask: true,
  });
}

function endLoading() {
  //延迟200ms,防止太快
  setTimeout(function () {
    if (isLoading) {
      uni.hideLoading();
      isLoading = null;
    }
  }, 200);
}

// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    if (config.loading) {
      startLoading();
    }
    const userStore = useUserStore();
    const token = userStore.token;
    if (token) {
      config.headers["Authorization"] = token;
    }
    return config;
  },
  (error) => {
    return error;
  }
);
// 添加响应拦截器
instance.interceptors.response.use(
  (response) => {
    const { config, data } = response;
    if (config.message) {
      const { success, message, msg } = data;
      if (success) {
        uni.showToast({
          icon: "success",
          title: "操作成功",
        });
      } else {
        message &&
          uni.showToast({
            icon: "error",
            title: message,
          });
        msg &&
          uni.showToast({
            icon: "error",
            title: msg,
          });
      }
    }
    endLoading();
    return response;
  },
  (error) => {
    const response = error?.response;
    if (response) {
      const { status } = response;
      switch (status) {
        case 401:
          const userStore = useUserStore();
          userStore.setToken();
          userStore.setUserInfo();
          window.location.reload();
          break;
        default:
          break;
      }
    }
    const config = error?.config;
    if (config?.loading) {
      endLoading();
    }
    return error;
  }
);

export default instance;