霸榜掘金!轻量级请求策略库 alova 出炉!

发布一下 0 0

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

霸榜掘金!轻量级请求策略库 alova 出炉!

高级前端进阶

前言

今天在掘金上看到了一篇热文,题目是《是时候该换掉你的 axios 了》。当时眼前一亮,以为又有什么新请求方案出来了,以前也尝试讨论过 xhr、fetch、axios、甚至 Redaxios(体积只有 800 字节),看得出来大家对这一类文章都比较感兴趣,毕竟大多数情况下都需要面对它们。所以这次也一样,决定一探究竟,看看能给大家带来什么干货。

以下是已发布文章传送门:

  • 《为什么 JS 开发者更喜欢 Axios 而不是 Fetch?》
  • 《Ajax 会被 fetch 取代吗?Axios 怎么办?》
  • 《谁在动 Axios 的奶酪!它叫 Redaxios!》
  • 《为何需要 Axios!Axios 的 5 个热门替代方案!》
  • 《Node 原生支持 fetch!不是浏览器那个 fetch!》

话不多说,直接开始进入 alova 介绍的正题!

1.什么是 alova?

alova 是轻量级的请求策略库(注意策略两个字,与其他请求库有差异),它针对不同请求场景分别提供了具有针对性的请求策略,来提升应用可用性、流畅性,降低服务端压力,让应用如智者一般具备卓越的策略思维。

霸榜掘金!轻量级请求策略库 alova 出炉!

alova 核心模块提供了各类适配器接口(如:XMLHttpRequest、axios、Taro、Uniapp 等等),中间件机制来保证高扩展能力,从而适用更多的请求场景。

2.为什么需要 alova

数据请求一直是应用程序必不可少的重要部分,自从 XMLHttpRequest 诞生以来请求方案就层出不穷,客户端的数据交互探索一直聚焦于以下两个方向:

  • 使用更简单:如$.ajax、axios、react-query,以及 fetch api 等请求工具,编码形式从回调函数、Promise,再到 usehook ,难度越来越小。
  • 数据交互提示友好:比如:无状态(卡死状态);loading 进度条;骨架屏、占位等

除了这两个方面外,其实开发者还应该更多的关注应用的流畅性,比如:减少频繁的、重复的请求,内存缓存优化都是可行的方向。 alova 从请求策略入手,一方面通过 Client-Server 数据交互的高效管理提高了应用的流畅性,另一方面还可以降低服务端压力,在此基础上逐渐演变成了 RSM 的请求场景模型(下文会重点论述)。

alova 的高可扩展能力可以实现不同场景下的请求策略,通过简单编码即可快速上手。

3.alova 优势

alova 可以在编写少量代码的情况下,开箱即用地提升应用在请求方面的流畅性,同时保证了开发体验。与常见的请求库相比,alova 在体积上也有明显的优势,是 axios 的(11.1/4.3)1/2.6 倍,是 react-query 的 1/3(4.3k/13k)。

因此,在包体积敏感的场景可以尝试使用 alova。当然,我曾经也介绍过一个更小的请求库,即 Redaxios,它体积只有 800 字节,远小于 alova。

Redaxios 使用浏览器原生 fetch() 以 800 字节的形式实现了该 API。所有现代主流浏览器都支持它,并且也扩展到了很多前端基建场景,如: Next.js、Create React App 和 Preact CLI 等等

霸榜掘金!轻量级请求策略库 alova 出炉!

同时,alova 也提供了丰富的特性,满足 99%的请求场景,alova 具有以下特性:

  • 支持 vue、react、svelte 等框架,Typescript 开箱即用
  • alova 的 api 与 axios 类似,开箱即用的高性能请求策略,让应用更流畅
  • 体积只有 4kb(axios 的 30%+),同时支持 tree shaking
  • 高灵活性,请求库兼容性高,如 axios、superagent 或 fetch-api
  • 3 种数据缓存模式(如:内存模式、缓存占位模式、恢复模式等),提升请求性能,同时降低服务端压力
  • 高可扩展,可以自定义请求适配器、存储适配器、中间件,以及 states hook,请求共享,避免重复
  • 数据预拉取,用户可以更快看到信息,无需等待,同时支持实时自动状态管理

alova 的三种缓存模式分别对应于不同的场景,比如下面的内存模式:

lovaInstance.GET('/todo/list', {  // ...  localCache: {    // 设置缓存模式为内存模式    mode: 'memory',    // 单位为毫秒    // 当设置为`Infinity`,表示数据永不过期,设置为0或负数时表示不缓存    expire: 60 * 10 * 1000,  },});

缓存占位模式下,data 将立即被赋值为上次缓存的旧数据,可以判断如果有旧数据则使用它替代 Loading 展示,同时它将发送请求获取最新数据并更新缓存,这样就达到了既快速展示实际数据,又获取了最新的数据。

const todoListGetter = alovaInstance.Get('/todo/list', {  // ...  localCache: {    // 设置缓存模式为持久化占位模式    mode: 'placeholder',    // 缓存时间    expire: 60 * 10 * 1000,  },});

恢复模式下,服务端缓存数据将持久化,如果过期时间未到即使刷新页面缓存也不会失效,它一般用于一些需要服务端管理,但基本不变的数据。

const todoListGetter = alovaInstance.Get('/todo/list', {  // ...  localCache: {    // 设置缓存模式为持久化模式    mode: 'restore',    // 缓存时间    expire: 60 * 10 * 1000,  },});

4.alova 和请求库的关系

4.1 什么是 RSM

alova 的创建初衷是对不同请求场景提出的一个解决方案,它可以更简洁优雅地实现体验更好,性能更好的请求功能,是一个 RSM(Request Scene Model) 实现库。

霸榜掘金!轻量级请求策略库 alova 出炉!

而例如:$.ajax、axios 和 fetch-api 等对请求发送和响应接收提供了很好的支持,它们是 RSM 流程中必不可少的一个环节(请求事件环节),alova 仍然需要依靠它们进行请求,因此我们可以将 alova 看作是请求库的一种武装,让请求库变得更加强大。

4.2 RSM 的 4 个阶段

请求时机

在 alova 中提供了 useRequest、useWatcher、useFetcher 三种 use hook 实现请求时机,由它们控制何时应该发出请求,同时将会创建和维护状态化的请求相关数据,如 loading、data、error 等,无需自主维护这些状态。

const App = () => {  const {    // loading是加载状态值,当加载时它的值为true,结束后自动更新为false    // 它的值为普通的boolean值,请求状态变化时内部将自动调用set函数更新它的值    loading,    // 响应数据    data,    // 请求错误对象,请求错误时有值,否则为undefined    error,    // 直接将Method实例传入即可发送请求  } = useRequest(todoListGetter, {    // 请求响应前,data的初始值    initialData: [],  });  // 你可以直接使用 todoList 来渲染 todo 列表  if (loading) {    return <div>Loading...</div>;  } else if (error) {    return <div class="error">{error.message}</div>;  } else {    return (      <>        <div v-for="todo in data">          <div class="todo-title">{todo.title}</div>          <div class="todo-time">{todo.time}</div>        </div>      </>    );  }};

请求行为

描述以怎样的方式处理请求,在 alova 中以 method 对象实现。

const getTodoList = currentPage => {    return alovaInstance.Get('/todo/list', {        // 注意:这边设置了name属性,用于在无法直接指定Method实例时,过滤出需要的Method实例        name: 'todoList',        params: {            currentPage,            pageSize: 10        }    });};const App = () => {    const {        // fetching属性与loading相同,发送拉取请求时为true,请求结束后为false        fetching,        error,        onSuccess,        onError,        onComplete,        // 调用fetch后才会发送请求拉取数据,可以重复调用fetch多次拉取不同接口的数据        fetch    } = useFetcher();    // 在事件中触发数据拉取    const handleSubmit = () => {        // 假设已完成todo项的修改...        // 开始拉取更新后的数据        // 情况1:当你明确知道拉取todoList第一页数据时,传入一个Method实例        fetch(getTodoList(1));        // 情况2:当你只知道拉取todoList最后一次请求的数据时,通过Method实例匹配器来筛选        fetch({            name: 'todoList',            filter: (method, index, ary) => {                // 返回true来指定需要拉取的Method实例                return index === ary.length - 1;            }        });    };    return (        {/* 渲染统一的拉取状态 */}        { fetching ? <div>{{ 正在后台拉取数据... }}</div> : null }        {/* ... */}        <button onClick={handleSubmit}>修改todo项</button>    );};

请求事件

表示携带请求参数发送请求以获得响应,alova 可以与 axios、fetch、XMLHttpRequest 等任意请求库或原生方案共同协作。

下面使用 xhrRequestAdapter 作为 alova 的 xhr 请求适配器。

import { createAlova } from 'alova';import { xhrRequestAdapter } from '@alova/adapter-xhr';const alovaInst = createAlova(  requestAdapter: xhrResponseAdapter(),);

下面使用 axiosRequestAdapter 作为 alova 的请求适配器。

import { createAlova } from 'alova';import { axiosRequestAdapter } from '@alova/adapter-axios';const alovaInst = createAlova(  requestAdapter: axiosResponseAdapter(),);

下面调用 AdapterTaro 适配 taro 将返回请求适配器、存储适配器,以及 ReactHook,因此不需要设置这三个项,使用方法完全一致。

import { createAlova } from 'alova';import AdapterTaro from '@alova/adapter-taro';const alovaInst = createAlova(  (baseURL: 'https://api.alovajs.org'),  ...AdapterTaro());

响应数据管理

alova 将响应数据状态化,并统一管理,任何位置都可以对响应数据进行操作,并利用 MVVM 库的特性自动更新对应的视图。

当响应数据结构不能直接满足需求时,可以为 method 实例设置 transformData 钩子函数将响应数据转换成需要的结构,数据转换后将会作为 data 状态的值。

const todoListGetter = alovaInstance.Get('/todo/list', {  params: {    page: 1,  },  // 函数接受未加工的数据和响应头对象,并要求将转换后的数据返回,它将会被赋值给data状态。  // 注意:rawData一般是响应拦截器过滤后的数据,响应拦截器的配置可以参考[设置全局响应拦截器]章节。  transformData(rawData, headers) {    return rawData.list.map((item) => {      return {        ...item,        statusText: item.done ? '已完成' : '进行中',      };    });  },});

5.本文总结

文章到这里,大家应该都大概了解 alova 了,也明白为什么开头提示大家注意下请求策略库中的策略二字了。因为,alova 就不是一个请求库,这点和 xhr、fetch、axios、甚至 Redaxios 都有本质上的差异,前者是后者的进一步包装,相当于完整的、一体化的解决方案,至于底层请求库,则不作强依赖。

只是这种包装方案不是每个开发者都有述求,也不是所有项目都需要,所以从掘金的评论上看,大家并不怎么看好,认为是又一个轮子。目前 alova 在 github 上只有 100 个 star,为了鼓励下作者,毫不犹豫的支持了一下。值得一提的是,这个请求策略库的作者是国内的开发者,再次点赞一下吧!

不过,就我个人而言,我还是倾向于使用 Axios、如果包体积很敏感会尝试 Redaxios。不过,行文至此,就当一次对 alova 的宣传吧,毕竟开源不易!

参考资料

https://alova.js.org/zh-CN/overview/index

https://github.com/alovajs/alova

https://alova.js.org/zh-CN/extension/alova-adapter-taro

https://alova.js.org/

https://juejin.cn/post/7213923957824979000

https://www.npmjs.com/package/alova

https://alova.js.org/zh-CN/get-started/response-cache

版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/205315.html