改变 axios 的用法后,我的工作效率提升了 3 倍

263 天前
 ScottHU

实际场景下的请求问题

作为前端开发,网络请求肯定是我们经常要面对的事情,在前端请求中,axios 和 fetch API 应该是我们最常用的请求工具了,它们在发送请求和接收响应数据已经做到了足够简单。

但在实际项目中,为了达到更好的用户体验,我们还需要考虑下面这几个因素:

  1. 展示加载中的请求状态
  2. 展示请求错误状态
  3. 展示上传/下载文件的进度信息

上面这些都需要我们编写额外的代码,增加了不少的工作量,你的请求代码可能是下面这样的,我们以 vue3 代码为示例。

const loading = ref(false);  
const data = ref({});  
const error = ref(null);  
const request = async () => { 
  try {  
    loading.value = true;  
    data.value = await axios.get('/xxx');  
  } catch (e) {  
    error.value = e;  
  }
  loading.value = false;  
};
onMounted(request);

如果面对大量的 api ,这工作量可想而知,想到这时就有点头疼啊。有没有一种方法可以自动帮我处理这些逻辑,让请求代码看起来更简洁呢?

解决

我们可以用封装的思路,把上面这些都封装为一个简单的 use hook ,就可以很好地解决了,封装后的代码大概是下面这样的。

export const useRequest = (url) => {
  const loading = ref(false);
  const data = ref({});
  const error = ref(null);
  const request = async () => {
    try {
      loading.value = true;
      data.value = await axios.get(url);
    } catch (e) {
      error.value = e;
    }
    loading.value = false;
  }
  onMounted(request);

  return {
    loading,
    data,
    error
  };
}

这是一个最简单的 use hook 实现,它帮我们解决了请求模板代码的问题。当然你还可以使用 use hook 封装更多更高级的请求功能,而这些功能现在不必你自己封装了,使用alova就可以了。

alova 是一个轻量级的请求策略库,针对分页请求、表单提交、上传和下载文件等不同请求场景使用对应的请求模块,让开发者使用非常少量的代码就可以实现高可用性和高流畅性的请求功能,这意味着,你再也不需要自己绞尽脑汁编写请求优化代码,再也不需要自己维护请求数据和相关状态,你只需要选择并使用请求模块,设置参数后,alova 帮你搞定!

在引入 alova 后,我的工作效率直接提高了 3 倍,强烈推荐给大家。

你可以将 alova 理解成是 axios 或 fetch-api 等请求工具的一种武器装备,将 alova 与请求工具配合使用将会让它们变得更加强大。

其实,alova 底层依然依赖 axios 或 fetch-api 等请求函数进行请求,因此你仍然可以使用你喜欢的请求库。

以下是一个基于vue3+axios+alova的使用示例,alova 将自动为你创建请求相关的,可以直接用于视图的响应式状态,代码如下:

可运行的示例点此去查看

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">{{ error.message }}</div>
  <span v-else>responseData: {{ data }}</span>
</template>

<script setup>
import { createAlova, useRequest } from 'alova';
import VueHook from 'alova/vue';
import { axiosRequestAdapter } from '@alova/adapter-axios';

const alovaInstance = createAlova({
  statesHook: VueHook,

  // 设置使用 axios 作为请求工具
  requestAdapter: axiosRequestAdapter()
});

const {
  // 加载状态
  loading,

  // 响应数据
  data,

  // 错误信息,请求错误时才有值
  error
} = useRequest(alovaInstance.Get('/todoList'));
</script>

是不是非常 nice !!!之前需要我们自己实现的各种功能,alova 都帮我们做了。

总结

alova 目前提供了 8 种请求策略,如果你希望在不同的请求场景下方便地实现特定的请求需求,那千万别错过它哦。alova 还提供了缓存管理、请求共享等更多功能,可以覆盖绝大多数请求场景。

所以,在你的下一个项目中,你也可以来试试 alova ,一定能给你带来更愉快的开发体验!

结尾

目前,alova 已经可以在 vue options ( vue2 和 vue3 )写法中完美使用了,点此查看详情。后续还会支持以下框架:

如果觉得对你有用请帮忙点个赞或收藏!

相关信息

alova 官网

alova Github 地址

5287 次点击
所在节点    JavaScript
32 条回复
8520ccc
263 天前
ahook ?似乎也是提供这个功能的
NessajCN
263 天前
https://v2ex.com/t/948621
被喷了上百楼又来了吗
dropice7777777
263 天前
你们今天是集体出动了吗?掘金才刚看到推文,这里又看到了
poorAshenOne
263 天前
我用了之后是不是就能提前下班了
BaiLinfeng
263 天前
我还以为是技术交流文章,仔细一看是推广广告啊
MRG0
263 天前
比 axios 没有明显优势,咋立的项
XIVN1987
263 天前
@poorAshenOne

你老板就可以给你布置三倍任务了 ;-)
a632079
263 天前
这个不是 swr 做的事情么……😨 Nuxt 3 的话有内嵌的 useFetch useAsyncData……vite vue 的话,用 https://github.com/Kong/swrv 足以。楼主如果真要推广的话,不妨和这类库对比一下,给出数据来。而不是写软文……假设大家都不知道一样。
haierspi
263 天前
老板: 看你天天没啥事... 工作很不饱和啊.. 要不签个字吧.. 把你工作交接下..
FakerLeung
263 天前
上次还没被喷过瘾吗?
jsq2627
263 天前
这是不吸取教训吗。。
Quarter
263 天前
好奇这个三倍是怎么得出来的
webszy
263 天前
没看出来比我自己封装的 axios 好在哪
jorneyr
263 天前
比这个还简洁?

* [1] 普通 GET 请求
* 提示: rsp 会自动推导出类型 Response<string>,不需要明确的写。
* Rest.get<string>('/api/rest').then(rsp => {});
*
* Rest.data({ pageNumber: 3 }).get<string>('/api/rest').then((rsp: Response<string>) => {
* console.log(rsp);
* });
*
* 其他类型的请求只需要把 get<T>() 替换为对应的函数即可,参数配置部分一样。
*
* [2] 替换 url 中的变量: 下面的 URL 中 {bookId} 会被替换为 params 的参数 bookId 的值 23 ,得到请求的 url '/rest/books/23'
* Rest.url('/rest/books/{bookId}').params({ bookId: 23 }).data({ name: 'C&S' }).update<boolean>().then(rsp => {
* console.log(rsp);
* });
*
* [3] 调用 useRequestBody() 使用 request body 传输复杂的 data 对象 (对象可以有多级属性)
* Rest.url('/api/uid').data({
* user: { username: 'Bob', password: '123456' },
* company: 'App'
* }).useRequestBody().create<User>().then(({ data: user, success, message }) => {
* console.log(user);
* });
*
* 默认使用 application/x-www-form-urlencoded 的方式,即普通表单的方式。
*
* [4] Axios 不支持同步请求,但可以在同一个函数里使用 async await 进行同步操作:
* async function syncFunc() {
* const r1 = await Rest.get('/api/rest1'); // r1 为 resolve 的参数。
* const r2 = await Rest.data({ name: 'Goo' }).create<Foo>(/api/rest2');
*
* console.log(r1, r2);
* }
* 注: jQuery 的 Ajax 支持同步请求,但是新版本中也不推荐使用了,浏览器中会有警告。
*
* [5] 请求成功表示与服务器通信成功,不代码业务处理成功。
* 使用 Rest.normalize() 根据 success 对响应统一的进行业务逻辑判断,success 为 true 表示业务处理成功,为 false 表示失败。
* 代码中逻辑更关注成功业务处理,大多数时候都可以使用 Rest.normalize() 简化开发,除非 success 的值不足以判断,
* 需要使用响应的 code 进行更多情况处理。
*
* [5.1] Api 接口文件中处理请求。
* async function findTime(): Promise<number> {
* return Rest.get<number>(url).then(({ data: time, success, message }) => {
* // 提示: 参数里进行了一次解构是为了让调用者知道 data 的业务名称,方便代码的维护。
* return Rest.normalize({ data: time, success, message });
* });
* }
*
* [5.2] Vue 文件中调用请求直接获取结果,忽略请求的细节,而且即使切换了 Api 的实现不需要修改 vue 中的代码 (如把 Axios 换为 fetch 实现)。
* findTime().then((time: number) => {
* console.log(time);
* })
* const time: number = await findTime();
cnwhy
263 天前
api 请求就是你的工作全部么,这种文章真恶心人
justdoit123
263 天前
来来来,细说 3 倍效率怎么计算出来的!为什么是 3 而不是 100 ?写 100 会不会更吸引人?
duck2u
263 天前
useSWR
duck2u
263 天前
怎么念,啊 low 哇?
cppc
262 天前
味太浓了,你不搞这种技俩就不会说话了是吧
alleluya
262 天前
alova 我记得之前是不是有写过这种营销的文章? 而且这种 useRequest 式的封装 有很多选择啊 你这文章也没说明为啥一定要用你的 比别的好的地方在哪

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/979513

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX