做Vue项目就是无限封装之Axios的封装

69 阅读2分钟

目前为止,我已经学习了三种向网络发送异步请求的方式:XMLHttpRequest(简称XHR)、fetch和axios库。其中,前两者是浏览器自带的api,后者是一个第三方库。

XHR是比较早出现的用于在网页中发送异步请求的方式,替代了古老的在JSP中嵌入Java代码发送请求的方式。但这个api也有自己的缺点,比如最直观的就是书写起来十分繁琐,需要自己封装,虽然市面上也有很多已经封装好的XHR库,但依然不能避免它的第二个缺点,就是回调地狱。

后出现的fetch就比较好的解决了这个问题,因为它语法简单,直接调用api请求即可。而且支持Promise,这样就解决了在XHR中多重请求引发的回调地狱问题,代码简洁,易于阅读和维护。

但是即便如此,fetch也有它的不足之处:为了代码更高程度的复用性和可维护性,需要再次封装;另外,功能不够丰富,不能满足开发需求,比如没有拦截器功能;最后一点就是,fetch是浏览器支持的api,不能跨平台使用。

axios就很好解决了fetch的问题。axios底层将XHR包装成了支持Promise的对象,并且功能丰富,即开即用。但是在业务复杂的大型项目中,依然需要对axios进行封装,主要原因是为了避免日后出现优于axios的三方库,不能在所有组件中都使用axios,否则想要更换的话,重构工作是非常费时费力的。因此将axios封装为一个统一的类,只存在于一个文件中,这样axios就和这个项目低耦合了。

那么具体怎么做呢?废话不多说,直接上代码:

// request.js

/** 
    将axios实例封装到一个类中
    构造函数传递参数baseUrl,timeout
    构造函数内部将一个axios实例作为MyRequest的一个属性
    同时在这个类中创建自己的方法,方法实质就是对axios方法的封装
*/
class MyRequest{
   constructor(baseUrl, timeout){
      this.ins = axios.create({
          baseURL: baseUrl, 
          timeout: timeout
      })
   }
   
   request(config){
      return new Promise((resolve, reject)=>{
        /** 
            在then中的res,是经过axios包装的对象,出了data是服务器返回的数据外,还有
            status 表示状态码
            statusText 表示状态信息
            headers 响应头
            config 请求的配置
            request 就是请求本身
        */
        this.instance
            .request(config)
            .then(res => resolve(res))
            .catch(err => reject(err))
      })
   }
   
   get(config){
       return this.request({...config, method:'get'})
   }
   
   
   post(config) {
        return this.request({ ...config, method: 'post' })
   }
   
   // 还可以封装自己的patch/put等方法,省略不写了。
}

/**
    new 一个MyRequest实例并导出
    这样每次使用这个自己封装的类,都会自动创建一个对象
    BASEURL和TIMEOUT是一个常量,可以提出放在统一的文件中专门保管
*/
export default new MyRequest(BASEURL, TIMEOUT)


// Home.vue
<script setup>
  import myRequest from '@/service/request.js'
  
  const getTaskList = async ()=>{
    const {data} = await myRequest('/api/tasks') 
    return data.list;
  }
  
</script>