[网络] Axios 网络请求库讲解

[网络] Axios 网络请求库讲解

·

1 min read

对于axios的使用,我已不陌生,但是想要进一步的了解一些细节,所以就打算写一篇博客,用于总结;这篇博客主要是axiosts一起使用,并结合一些常见的业务场景来进行讲解

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)
  }
)

然后vuereact的导航有些不同

vuerouter是可以直接从声明router对象的文件中引入,并可以直接在.vue组件外直接使用的

reactrouter是通过useRouter获取的,由于hook只能在组件或其他hook中使用,所以还必须多下载一个history包才可以