axios二次封装

186 阅读2分钟

1.设置baseURL,timeout

// 配置新建一个 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 50000,
});

2.请求拦截器中添加token,自定义loadding

// 配置新建一个 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 50000,
  defaultLoadding: true,
});

// 添加请求拦截器
service.interceptors.request.use((config) => {
  const userInfoStore = useUserInfoStore(pinia);
  console.log(config, "zdrconfig");
  const { defaultLoadding, loadding } = config || {};
  const defaultHeader = {};
  if (userInfoStore.token) {
    defaultHeader.token = userInfoStore.token;
  }
  config.headers = { ...defaultHeader, defaultLoadding, loadding };
  return config;
});

// api 上的应用
export const getUserInfoApi = () => {
  return request.get<any, userInfoResponseModel>(Api.getUserInfo, { a: 1 });
};

3.响应拦截器中第一个参数是成功的callback,第二个参数是失败的callback

在第一个callback对code不等于200的接口做全局统一错误提示
如果是401的code,要把token,name,等用户信息都重置为空,并中断Promise链(返回一个reject的Promise)
在第二个callback中进行错误提示,并返回错误状态Promise

4.取消重复请求

// 所有请求列表容器
const requestListMap = new Map();
/**
 * 每一个请求生成一个唯一的key
 * @param config 请求配置对象
 * @returns 唯一的key
 */
function getRequestKey(config: AxiosRequestConfig) {
  const { url, method, params = {}, data = {} } = config;
  return [url, method, JSON.stringify(params), JSON.stringify(data)].join("&");
}
const CancelToken = axios.CancelToken;
/**
 * 删除请求key并取消请求
 * @param config
 */
function removeRequestKey(config: AxiosRequestConfig, completed?: boolean) {
  const requestKey = getRequestKey(config);
  if (requestListMap.has(requestKey)) {
    const { cancel } = requestListMap.get(requestKey);
    !completed && cancel(); // 取消还未执行完的请求
    requestListMap.delete(requestKey);
  }
}

/**
 * 添加请求key
 * @param config
 */
function addRequestKey(config: AxiosRequestConfig) {
  const requestKey = getRequestKey(config);
  config.cancelToken = new CancelToken((cancel) => {
    // new Promise((resolve, reject) => {})
    if (!requestListMap.has(requestKey)) {
      requestListMap.set(requestKey, {
        cancel,
        pathname: window.location.pathname,
      });
    }
  });
}
request.interceptors.request.use((config) => {
  const token = useUserStore().token;
  if (token) {
    config.headers.token = token;
  }
  // 第二个重复的请求会立马被删掉
  removeRequestKey(config); // 删除key   取消前面已发送但还未完成的相同请求
  addRequestKey(config); // 添加key    缓存用于取消当前请求的cancel函数
  return config;
});

// 文字总结:
1.创建一个map结构
2.把每次请求的url,请求方式,请求参数拼接成map的key,然后封装两个函数,第一个函数删除之前存过key,和取消请求cancel的方法,第二个函数是添加每个请求的key和存当前的cancle函数以及当前的pathname(window.location)

5.取消上一个页面的请求

import { requestListMap } from '@/utils/request';

router.beforeEach((to, from, next) => {
  requestListMap.forEach((value, key) => {
    const { pathname, cancel } = value;
    if (pathname !== to.path) {
      cancal();
      requestListMap.delete(key);
    }
  })
})