前言
有过工作经验的小伙伴应该对axios二次封装比较熟悉,但是加入ts后就比较犯难,被ts的数据格式校验搞的头大,接下来就简单分析一下axios,作者版本"axios": "^1.6.8",
引入axios以及实例化
import axios from "axios";
import type { InternalAxiosRequestConfig, AxiosError, AxiosRequestConfig } from "axios"
const service = axios.create({
baseURL: import.meta.env.BASE_URL,
timeout: 30000
})
设置请求拦截器以及了解 InternalAxiosRequestConfig内置数据类型
首先,我们找到axios包下面index.d.ts声明文件
interceptors.request就是我们要设置的请求拦截器,接下来再看InternalAxiosRequestConfig类型设置
InternalAxiosRequestConfig继承了AxiosRequestConfig类型并配置了headers属性
接下来实现一下请求拦截器的代码
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = getToken()
// 配置请求权限
if (token) {
config.headers["Authorization"] = 'Bearer ' + token
}
return config
},
(error: AxiosError) => {
Promise.reject(error)
}
)
如果将InternalAxiosRequestConfig换成了AxiosRequestConfig,编辑器会给出错误提示
设置响应拦截器,响应数据有代码提示
还是先看源码
axios实例,request接受一个泛型T, 返回一个Promise, D为请求参数data泛型约束,这里不做介绍。再看这个AxiosResponse<T>
这个泛型T也就是request接受的第一个泛型T用于约束response中的data
代码实现
type Data<T> = {
status: number,
msg: string,
result: T
}
// 暴露一个异步函数,接受一个泛型T传入Data,再将Data<T>传入service.request
export default <T>(config: AxiosRequestConfig) => {
return new Promise<Data<T>>((res, rej) => {
service
.request<Data<T>>(config)
.then((response) => {
// 打印结果如下
console.log(response);
// 请求成功 返回接口数据
res(response.data);
// 请求失败 rej()
})
.catch((err: any) => {
console.log(err);
// 处理错误逻辑
rej(err);
});
});
};
代码测试
import request from "@/utils/request";
import type { UserInfo } from '../types/user'
export const getUserInfo = () => {
// 如果返回的是数组格式 UserInfo改为UserInfo[]
return request<UserInfo>({
method: 'get',
url: '/api/userInfo',
})
}
ps: 如果代码修改完成,接口返回数据还没有提示,可以重启编辑器
完整代码
import axios from "axios";
import type { InternalAxiosRequestConfig, AxiosError, AxiosRequestConfig, AxiosResponse } from "axios"
import { getToken } from "./token";
const service = axios.create({
baseURL: import.meta.env.BASE_URL,
timeout: 30000
})
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = getToken()
// 配置请求权限
if (token) {
config.headers["Authorization"] = 'Bearer ' + token
}
return config
},
(error: AxiosError) => {
Promise.reject(error)
}
)
// 在这里没有找到泛型约束的方法
service.interceptors.response.use()
// 根据实际情况自行修改
type Data<T> = {
status: number,
msg: string,
result: T
}
// 暴露一个异步函数,接受一个泛型T传入Data,再将Data<T>传入service.request
export default <T>(config: AxiosRequestConfig) => {
return new Promise<Data<T>>((res, rej) => {
service
.request<Data<T>>(config)
.then((response) => {
// 打印结果如下
console.log(response);
// 逻辑自行处理
if (response.data.status === 0) {
// 返回接口数据
res(response.data);
} else {
rej(response.data)
}
})
// AxiosError同样支持泛型约束,第一个泛型参数 约束err.response.data
.catch((err: AxiosError<Data<T>) => {
console.log(err);
// 处理错误逻辑
rej(err);
});
});
};
本篇文章到这里就结束了,希望对小伙伴们有帮助,如果有更加优雅的实现方式,欢迎评论区留言