一、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;
}
}
}