0


vue3项目中封装axios

目前前端最流行的网络请求库还是axios,所以对axios的封装很有必要,此次基于vue3+ts的环境下。

axios的基本使用

import axios from'axios'// console.log('adh')
axios.get('http://XXX.xxx.xxx.xxx:8000/home').then((res)=>{
  console.log(res.data)})

axios.get()会返回一个Promise对象,所以可以用.then获取返回的数据。

axios.all()方法

axios.all([
  axios.get('http://httpbin.org/get').then((res)=>{
    console.log(res.data)}),
  axios.post('http://httpbin.org/post').then((res)=>{
    console.log(res.data)})])

axios一些基本配置

在axios中,有一些默认配置,它们是存在于axios.defaults中的,比如我们经常会用到的baseURL、timeout属性

axios.defaults.baseURL ='http://httpbin.org'
axios.defaults.timeout =10000

axios的拦截器

在平常的使用中,我们经常需要对axios请求进行拦截以处理一些特殊情况,如获取token、处理异常等,这时候我们就需要使用axios的拦截器()。

axios.interceptors.request.use((config)=>{return config
  },(error)=>{return error
  })
axios.interceptors.response.use((res)=>{
    console.log(res.data)},(error)=>{return error
  })

如上,axios.interceptors.request是对请求的拦截,此时可以为请求添加headers,添加token等操作,二axios.interceptors.response则是对请求的返回进行拦截,在此处我们可以统一返回的数据结构以及对错误进行一些统一的处理

封装axios-封装基础属性

首先,我们先确认一下基本思路,我们把主要的逻辑封装成一个类,然后编写一个出口文件,将该类导出,需要注意的是,往这个类中传入哪些参数,诚然,我们可以直接在类中定义诸如BASE_URL、timeout、interceptors等axios的属性或方法,但是为了今后的可适配性更高,我们应该尽量的把可配置的属性作为变量传入我们欲封装的类中,下面先进行一个基本的封装:

// 封装类import axios from'axios'import{ AxiosInstance, AxiosRequestConfig }from'axios'classZWRequest{instance: AxiosInstance
  constructor(config: AxiosRequestConfig){this.instance = axios.create(config)}request(config: AxiosRequestConfig):void{this.instance.request(config).then((res)=>{
      console.log(res)// 此处能成功打印出结果代表成功})}}exportdefault ZWRequest
// 出口文件index.tsimport ZWRequest from'./request'import{BASE_URL, timeout }from'./request/config'const zwRequest =newZWRequest({baseURL:BASE_URL,// 配置参数timeout: timeout // 配置参数})exportdefault zwRequest
// 在main.ts中测试import ZWRequest from'./service/index.ts'
ZWRequest.request({url:'/post',method:'POST'})

封装拦截器

上面的封装可以传入BASE_URL、timeout等一些基础属性,但是对于拦截器interceptors还是不能实现配置,所以下一步我们改造一下使其可以传入拦截器:

// 封装类import axios from'axios'import{ AxiosInstance, AxiosRequestConfig, AxiosResponse }from'axios'// 自建一个用于匹配interceptors的类型interfaceZWRequestInterceptors{
  requestInterceptor?:(config: AxiosRequestConfig)=> AxiosRequestConfig // 这是个函数类型
  requestErrorInterceptor?:(error: any)=> any
  responseInterceptor?:(config: AxiosResponse)=> AxiosResponse
  responseErrorInterceptor?:(error: any)=> any
}/** 再新建一个一个类型继承AxiosRequestConfig类型,并在其中设立一个属性,
该属性对应上一步建立的类型,如此,我们就可以用这个类型来代替封装类
的constructor()函数传入的参数类型了,在此基础上,完成对拦截器参数的传入。*/interfaceZWRequestConfigextendsAxiosRequestConfig{
  interceptors?: ZWRequestInterceptors
}classZWRequest{instance: AxiosInstance
  interceptors?: ZWRequestInterceptors
  constructor(config: ZWRequestConfig){this.instance = axios.create(config)this.interceptors = config.interceptors
    this.instance.interceptors.request.use(this.interceptors?.requestInterceptor,this.interceptors?.requestErrorInterceptor
    )this.instance.interceptors.response.use(this.interceptors?.responseInterceptor,this.interceptors?.responseErrorInterceptor
    )}request(config: ZWRequestConfig):void{this.instance.request(config).then((res)=>{
      console.log(res)})}}exportdefault ZWRequest
// 出口函数index.ts/** 我们可以在出口函数中同意规定拦截器的形式以及相应的处理,这样做的好处是如果我们想
再生成一个可用的axios对象,如ZWRequest2,而且想实现与ZWRequest不一样的拦截方法,那么
就只需要在该页面再新创建一个对象即可 */import ZWRequest from'./request'import{BASE_URL, timeout }from'./request/config'const zwRequest =newZWRequest({baseURL:BASE_URL,timeout: timeout,interceptors:{requestInterceptor:(config)=>{
      console.log('发送请求成功11', config)return config
    },responseInterceptor:(res)=>{
      console.log('返回成功11', res)return res
    }}})const zwRequest2 =newZWRequest({baseURL:BASE_URL,timeout: timeout,interceptors:{requestInterceptor:(config)=>{
      console.log('发送请求成功22', config)return config
    },responseInterceptor:(res)=>{
      console.log('返回成功22', res)return res
    }}})exportdefault zwRequest
// main.ts中实验
ZWRequest.request({url:'/post',method:'POST'})
ZWRequest2.request({url:'/post',method:'POST'})

封装公用的拦截器

上面的封装中,拦截器是由每个实例传入的,但是有时候我们就是想所有的实例都拥有共同的拦截器,那么我们就需要在axios封装类里面添加共有的拦截器了(实例传入的拦截器也并不会被取消),只需要在axios封装类中添加以下代码即可实现全局的拦截:

this.instance.interceptors.request.use((config)=>{
        console.log('共有的请求时成功拦截')return config
      },(error)=>{
        console.log('共有的请求时失败拦截')return error
      })this.instance.interceptors.response.use((res)=>{
    console.log('共有的返回时成功的拦截')return res
  },(error)=>{
    console.log('共有的返回时失败的拦截')return error
  })

对单个请求传入拦截器

其实上面对拦截器的封装已经基本可以满足平时的开发需求了,但是如果你想更灵活些,比如每个请求都可以传入自己的拦截器,那么请往下看,如果我们需要再请求时传入拦截器,那么就需要看看我们是怎么调用的。目前,我们采用ZWRequest.request(config)的方式调用axios请求,很显然,在封装类中,config参数的类型是:AxiosRequestConfig,这个类型很显然不能传入拦截器参数。

request(config: AxiosRequestConfig):void{this.instance.request(config).then((res)=>{
     console.log(res)})}

所以为了能够往request方法中传入拦截器参数,我们需要将AxiosRequestConfig类型化成我们上面新建立的类型ZWRequestConfig,这样就可以从单个请求处传入各自的拦截器了。

// 改造axios封装类中的request方法request(config: ZWRequestConfig):void{// 对单独请求传来的拦截器进行处理if(config.interceptors?.requestInterceptor){
      config = config.interceptors?.requestInterceptor(config)}this.instance.request(config).then((res)=>{if(config.interceptors?.responseInterceptor){
        res = config.interceptors?.responseInterceptor(res)}
      console.log(res)})}// 在main.ts中进行测试
ZWRequest.request({url:'/post',method:'POST',interceptors:{requestInterceptor:(config)=>{
      console.log('单独请求的请求成功拦截')return config
    },responseInterceptor:(res)=>{
      console.log('单独请求的响应成功拦截')return res
    }}})

可以正常打印,成功!

对request请求方法封装

上面其实已经对request请求进行了大部分的封装了,但是此时的各种返回还局限在类里面,我们在main.ts中是无法拿到的,那么想要拿到返回值,我们就需要进一步操作,其实就是利用promise将结果返回出来:

// 对request方法的改造
request<T>(config: ZWRequestConfig): Promise<T>{returnnewPromise((resolve, reject)=>{// 对单独请求传来的拦截器进行处理if(config.interceptors?.requestInterceptor){
      config = config.interceptors?.requestInterceptor(config)}if(config.showLoading ===false){// 代表该请求不想显示加载动画this.showLoading = config.showLoading
    }this.instance
      .request<any,T>(config).then((res)=>{// 每次请求返回后将showLoading的值改为默认值,以免被这次请求穿的配置影响下一次请求的加载动画显示this.showLoading =DEFAULT_LOADINGif(config.interceptors?.responseInterceptor){
          res = config.interceptors?.responseInterceptor(res)}resolve(res)
        console.log(res)}).catch((error)=>{
        console.log(error)this.showLoading =DEFAULT_LOADINGreject(error)})})}// 在main.ts中实验interfacedataType{data: any
  returnCode: string
  success: boolean
}
ZWRequest.request<dataType>({url:'/home/multidata',method:'GET'// showLoading: false}).then((res)=>{
  console.log(res.data)
  console.log(res.returnCode)
  console.log(res.success)})

由上可见,其实操作很简单,那么接下来即使利用已经写好的request方法来些各种常用的请求调用方法了,就不多做赘述了,代码如下:

get<T>(config: ZWRequestConfig): Promise<T>{returnthis.request<T>({...config,method:'GET'})}
post<T>(config: ZWRequestConfig): Promise<T>{returnthis.request<T>({...config,method:'POST'})}delete<T>(config: ZWRequestConfig): Promise<T>{returnthis.request<T>({...config,method:'DELETE'})}

以上就是本人对axios的全部封装,完毕!


本文转载自: https://blog.csdn.net/weixin_44416058/article/details/124699253
版权归原作者 飞翔的波斯猫 所有, 如有侵权,请联系我们删除。

“vue3项目中封装axios”的评论:

还没有评论