对于axios
的使用,我已不陌生,但是想要进一步的了解一些细节,所以就打算写一篇博客,用于总结;这篇博客主要是axios
和ts
一起使用,并结合一些常见的业务场景来进行讲解
axios 实例的基础封装
基础的步骤如下:
创建一个
axios instance
,配置其baseURL
,有需要的话就配置一下代理为
axios instance
添加拦截器,处理错误、请求、响应
axios 请求头注意事项
默认情况下,axios
发起请求会将Conten-Type
设置为json
格式,所以我们如果想要发送其他格式的请求的话,需要在axios
实例发起请求的第三个参数中配置headers
,如下:
export const patchImport = async (payload: FormData) => {
const { data } = await test2Instance.post<any>(
"/enterprise/import",
payload,
{
headers: {
"Content-Type": "multipart/form-data" // 配置其他类型的请求
}
},
)
return data
}
axios 拦截器的注意事项
默认情况下,在后端返回数据经过axios
的拦截器后,axios
会将响应体数据默认再包裹一层data
字段;所以我们可以在拦截器中直接返回data
中的数据,减少层级,示例如下:
instance.interceptors.response.use(
(res: AxiosResponse) => {
return res.data
},
(err: AxiosError) => {
return Promise.reject(err)
}
)
这样写之后,你会发现axios
返回的数据的类型检验上是有问题的;因为axios
并不能自动推断拦截器所返回的数据类型,而是需要我们手动在axios
实例请求中声明类型,例如:
/**
这里 instance post 请求的返回类型实际上是 AxiosResponse<Person>
即使你在拦截其中返回的是 res.data 而不是 res
*/
await instance.post<Person>
我们直接来看 axios
对于其实例请求的类型声明:
request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>
可以看出,所有类型的请求都会返回一个Promise<R>
类型,并且request
的第一个泛型参数是T
,而第二个泛型参数R
如果不手动声明,那么默认就会包上一层AxiosResponse
,多出来的那一层data
就是这么来的
所以,我们可以不管第一个泛型参数,而是直接给第二个参数赋一个返回的数据类型,就可以使得axios
的类型校验争取
但是要注意:这里只是改变了类型声明而已,axios
并不会因为类型声明而改变其返回的数据的层级结构,我们必须要与axios
响应拦截器中的return
res.data
结合使用才是完全正确的
axios 登录过期重定向到登录页面
这是一个很常见的业务场景,通常结合router
的使用,让用户跳转到对应的界面就行了
首先我们需要判断响应状态码:
instance.interceptors.response.use(
(res: AxiosResponse) => {
// 响应状态码为 2xx 的时候会走这个函数
return res
},
(err: AxiosError) => {
// 响应状态码在 2xx 以外的会走这个函数
// 如果响应状态码为 401 未授权, 则导航到登录页
if(err.response.status === 401) {
// 执行导航重定向操作...
}
return Promise.reject(err)
}
)
然后vue
和react
的导航有些不同
vue
的router
是可以直接从声明router
对象的文件中引入,并可以直接在.vue
组件外直接使用的
而react
的router
是通过useRouter
获取的,由于hook
只能在组件或其他hook
中使用,所以还必须多下载一个history
包才可以