一、axios ts版本封装功能:
1、添加重复发送请求拦截器;
2、添加权限信息签名请求拦截器;
3、401重定向至登录页面;
4、添加泛型请求。
代码如下:
import { router } from '@/router';
import { Message } from 'element-ui';
import axiosRetry from 'axios-retry';
import { authUtils } from '@/util/auth';
import axios, { AxiosError, AxiosInstance, AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
export interface IDataWithError<T> {
  data: T;
  code: number;
  msg: string;
}
class HttpService {
  private http!: AxiosInstance;
  constructor() {
    this.http = axios.create({
      baseURL: authUtils.getBaseURL(),
      timeout: 60000,
    });
    axiosRetry(this.http, {
      retries: 3,
      shouldResetTimeout: true,
      // 重复请求延迟
      retryDelay: (retryCount: number) => {
        return retryCount * 1000;
      },
      retryCondition: (error: AxiosError) => {
        if (error.message.includes('timeout')) {
          return true;
        }
        return !error.response || error.response.status !== 401;
      },
    });
    this.addInterceptors(this.http);
  }
  get<T>(url: string, config?: AxiosRequestConfig) {
    return this.handleErrorWrapper<T>(this.http.get(url, config));
  }
  post<T>(url: string, param: unknown, config?: AxiosRequestConfig) {
    return this.handleErrorWrapper<T>(this.http.post(url, param, config));
  }
  postDownload<T>(url: string, param: unknown) {
    return this.handleErrorWrapper<T>(this.http.post(url, param, { responseType: 'arraybuffer' }));
  }
  put<T>(url: string, param: unknown, config?: AxiosRequestConfig) {
    return this.handleErrorWrapper<T>(this.http.put(url, param, config));
  }
  delete<T>(url: string, param: unknown, config?: AxiosRequestConfig) {
    return this.handleErrorWrapper<T>(this.http.delete(url, { data: param, ...config }));
  }
  private addInterceptors(http: AxiosInstance) {
    // 一、请求拦截器
    http.interceptors.request.use((config) => {
      // 1、添加token和项目id
      const token = authUtils.getToken();
      if (token) {
        config.headers['Authorization'] = 'Bearer ' + token;
        config.headers['ProjectId'] = authUtils.getProjectId();
      }
      // 2、验证请求状态码
      config.validateStatus = (status) => {
        switch (status) {
          case 401:
            const instance = Message.error('用户信息过期,请重新登录');
            setTimeout(() => {
              instance.close();
              router.push('/login');
            }, 1000);
            break;
          default:
            console.warn(`status= ${status}`);
            break;
        }
        return status >= 200 && status < 400;
      };
      return config;
    });
    // 二、响应拦截器
    http.interceptors.response.use(
      (response: AxiosResponse) => {
        return response;
      },
      (error) => {
        return Promise.reject(error);
      },
    );
  }
  private async handleErrorWrapper<T>(p: AxiosPromise): Promise<IDataWithError<T>> {
    return p
      .then((response) => {
        return response.data;
      })
      .catch((error: AxiosError) => {
        return {
          ...error.response?.data,
        };
      });
  }
}
export const httpService = new HttpService();
二、请求使用案例
2.1 新增api-type.ts接口类型声明文件
export interface IAccountMenuParam {
  roleId: string;
}
export interface IAccountMenuItem {
  title: string;
  /** 菜单组id */
  id: string;
  list: Array<IAccountMenuItemListItem>;
}
export interface IAccountMenuItemListItem {
  id: string;
  menuKey: string;
  name: string;
  /** 菜单组id */
  parentId: string;
  type: number;
  url: string;
}
2.2 新增api.ts文件
import { IAccountMenuItem, IAccountMenuParam } from './api-type';
import { httpService, IDataWithError } from './http-service';
/** 账户栏菜单 */
export function accountMenu(param: IAccountMenuParam): Promise<IDataWithError<IAccountMenuItem[]>> {
  return httpService.post(/api/v1/amz/accountMenu', param);
}
三、具体某个vue页面使用(ts版本)
导入该接口accountMenu
  // 账户栏菜单列表
private async getAccountMenuList() {
    const requestParam: IAccountMenuParam = {
      roleId: '1',
    };
    const res = await accountMenu(requestParam);
    if (res.code === 200) {
      const list =  res.data;
   }
  }
}