真没必要再对 axios 进行过度的封装

更新日期: 2022-05-31阅读: 1.1k标签: axios

很多同学喜欢对axios再进行二次的封装,但真的有必要吗?

前几天在某网站上看到一篇文章,说是用 ts 对 axios 进行了下封装,从点赞量、评论量和访问量上来看,有很多人都看过这篇文章了。

我之前也看过 axios 的源码,也基于 axios 进行过扩展和二次封装。对 axios 的内部原理和使用方式不可谓不熟悉。

虽然很多人在评论里说,收益匪浅啊,写的真棒啊等等,但我通读完整篇文章,得到的结论是: 完全没必要 。


1. 完全没必要

有的开发者喜欢基于 axios 再在外层封装一层,但这种方式实现的成本太高。

无论是实现跟 axios 一样的功能,还是外层进行简化,然后再按照 axios 的方式传给 axios,都增加了很多开发的成本。如:

const myAxios = async (config) => {
  /**
   * 中间各种封装,然后最后再使用axios发起请求
   * */
  try {
    const { status, data } = await axios(config);
    if (status >= 200 && status <= 304) {
      return data;
    }
  } catch (err) {
    console.error(err);
  }
  return null;
};

如有的开发者封装时,喜欢把 GET 请求方式的 params 字段和 POST 请求方式的 data 字段合并成一个,觉得可以减少使用者对字段记忆的成本。然后组件内部,再根据请求方式,决定传给 axios 的 params 字段还是 data 字段。或者有的屏蔽掉对请求的配置,有的屏蔽掉 axios 对外返回的字段。

就像上面的简要封装,连拦截器、取消请求等功能都给屏蔽掉了。但是,又想用,怎么办?那就靠着自己半吊子的知识,自己再封装一个,然后再跟 axios 进行对接,累不累啊。

有的人说他的要求更复杂,不二次额外封装一层,都没法用,比如:

  1. 一个 url 同时只有发起一个请求;

  2. 有重试的机制,当不满足要求时,最多可以重试 3 次;

  3. 统一的 loading 机制;

  4. 配置复杂,不同的 URL 有着不同的配置;

其实,上面的这几条需求,通过 axios 的拦截器就可以实现了,外面不用再封装一层。

axios 库本身就已经提供了多种的扩展方式,为什么不直接用呢?


1.1 方便扩展的适配器

axios 可以自定义请求适配器 adapter。

很多同学说 fetch 已经成为标准了,为什么 axios 内部还不支持。其实相比 XMLHttpRequest ,fetch 还是多少有点欠缺的,如取消请求的 AbortController 在 IE 浏览器中并没有实现,同时也不支持上传进度和下载进度。

因此,在 fetch 还没有对其 XMLHttpRequest 里的这些功能时,内部还很难使用 fetch 来实现。

若您真的想用 fetch 来进行请求,完全可以按照文档来扩展您的适配器。如何实现自定义的适配器,您可以参考这篇文章 如何实现 axios 的自定义适配器 adapter 。

直接在适配器上进行扩展,而不是基于 axios 再在外层封装一层,原因有几个:

  1. 不改变 axios 的使用方式,无论传参的方式,还是数据返回的格式,都没有任何的变化;

  2. 可以使用 axios 中提供的能力,如拦截器,转换请求数据和响应数据、支持防御 XSRF 等;

这种方式,对其他开发者也很友好,只要知道 axios 怎么用,就知道你封装的这个怎么用。不用增加学习的成本。


1.2 各种形式的配置

axios 在配置上,可以进行全局的配置和请求的单独配置,同时还有请求拦截器和响应拦截器,对某一类的请求进行处理。

若所有请求的 url 的 baseURL 是相同的,那么就可以在全局配置中进行配置;若某几个接口的 baseUrl 跟别的不一样,那么可以单独对其进行配置,或者在请求拦截器中,直接修改请求的 baseUrl。

axios.defaults.timeout = 6000; // 全局配置

/**
 * 拦截器中配置,若url中有`aaa`,则过期时间设置为4000ms
 **/
axios.interceptors.request.use(
  function (config) {
    if (/aaa/.test(config.url)) {
      config.timeout = 4000;
    }
    return config;
  },
  function (error) {
    return Promise.reject(error);
  },
);

axios('https://www.xiabingbao.com', { timeout: 2000 }); // 单独对某个请求进行配置

这些不同的配置方式,我个人觉得已经可以满足绝大部分的需求了。

1.3 本身就支持 typescript

axios 源码虽不是用 typescript 编写的,但官方也是提供了 ts 定义的: index.d.ts 。

那些上来就说用 typescript 封装 axios 的,你确定不是在搞笑吗?

而且,做为个人开发者,在开发和使用过程中,肯定会产生纰漏和 bug,比不过经过多人验证过的仓库。


2. 不是不能封装

其实也不是不能封装,毕竟 axios 做为一个通用的框架,它不可能适应所有的项目和架构。我不希望的是过度的封装,既没必要,又增加后来者的学习成本。

有的同学在 react/vue 中封装 axios,倒是 可以 有封装的意义,比如在 React 中封装一个请求的简单 hook 等。

const useAxios = (config) => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [result, setResult] = useState(null);

  useEffect(() => {
    setLoading(true);

    axios(config)
      .then(setResult)
      .catch(setError)
      .finally(() => {
        setLoading(false);
      });
  }, []);

  return { loading, error, result };
};

更具体的如何在 React 封装一个请求的 hook,可以参考该链接: 使用 react 的 hook 实现一个 useRequest 。

有的封装,是为了减少项目整体的改造成本,和其他人学习新用法的成本。比如之前我也基于 axios,在外层封装过一个请求库。当时为了跟之前的请求方式保持一致,就在外层额外封了一层。后来就出现当需要扩展功能时,特别麻烦,还不如从一开始设计时,就仅仅扩展他的适配器,或者几个简单的配置就行。

在封装的时候,首先我们要明白 axios 可以完成什么工作,他实现这些功能都有什么意义,为什么可以传入这些字段,又为什么要返回了那么多字段(我明明只需要接口返回的 data)?

想明白这些问题,就知道我们要保留什么,如何进行扩展和封装了。


3. 总结

我在很久之前写过一篇文章: 前端工程师如何通过造轮子提高自己 ,但似乎这篇文章的观点与之前的冲突了。

其实,并不冲突。造轮子是为了通过模仿成熟的作品来提高自己,但真的在实际应用时,我们就要考虑得更多。

自己实现出来的东西,大部分都比不上社区里经过千锤百炼验证过的。而且在使用的过程中,还要考虑减少其他人的学习成本。

比如你就不想用 Vue,觉得 Vue 这个框架优点大,然后选择了一个叫 mini-vue 的框架来开发项目。就社区完善程度来说,这个 mini 版肯定是比不上官方 Vue 的,后来者还得重新学习 mini 版的语法,当遇到问题时,都不知道去问谁,毕竟这个问题,只有 mini 版里才会有,其他人用的少,解答的人也少。

原文来自:https://juejin.cn/post/7103743662315536392

链接: https://fly63.com/article/detial/11623

axios处理Http请求的基本使用方法总汇

axios的功能特性:在浏览器中发送 XMLHttpRequests 请求,在 node.js 中发送 http请求,支持 Promise API,拦截请求和响应,转换请求和响应数据,自动转换 JSON 数据,客户端支持保护安全免受 XSRF 攻击

axios的特点与使用_解决处理axios兼容性问题

axios基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用。项目中发现,在安卓4.3及以下的手机不支持axios的使用,主要就是无法使用promise。加上以下polyfill就可以了。

axios常见传参方式_axios中get/post/put/patch请求

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。axios中get/post/put/patch请求。传参格式为 formData ,传参格式为 query 形式 ,传参格式为 raw等

axios-mock-adapter_一个axios调试好用的工具

axios-mock-adapter可以用来拦截http请求,并模拟响应,使用起来也很简单,比如你想模拟下服务器返回个500错误,什么404找不到、403禁止访问、500服务器错误、503服务不可用、504网关超时等等,你都能模拟出来

vue中axios的使用与封装

分享下我自己的axios封装,axios是个很好用的插件,都是一些params对象,所以很方便做一些统一处理。当然首先是npm安装axios 很简单。在src下新建文件夹 service / index.js,接着上代码

vue axios不缓存get请求(防止返回304不更新数据)

最近做项目遇到一款浏览器,由于缓存了get请求,导致不管如何刷新,数据都不更新的问题。以下分享一下解决办法:解决思路就是给每一条get请求增加一个timestamp的参数,value为时间戳

vue中axios请求的封装

发送请求模块目录,@/api/url中存放的是每个模块的URL,使用webpack提供的require.context将src/api/url下后缀为js的所有文件引入,并整理出一个对象。整合common.js & product.js,最终得到的对象如下:

axios基于常见业务场景的二次封装

axios的二次封装,功能实现:1.兼容ie浏览器避免缓存2.减少或更新重复请求3.接口域名使用环境变量4.全局loading状态5.可关闭的全局错误提醒6.可开启携带全局分页参数

Vue+Typescript中在Vue上挂载axios使用时报错

在vue项目开发过程中,为了方便在各个组件中调用axios,我们通常会在入口文件将axios挂载到vue原型身上,如下:这样的话,我们在各个组件中进行请求时

vue axios 拦截器

项目中需要验证登录用户身份是否过期,是否有权限进行操作,所以需要根据后台返回不同的状态码进行判断。axios的拦截器分为请求拦截器和响应拦截器两种。我一般把拦截器写在main.js里。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!