是時候該換掉你的 axios 了

首先我想聲明的是,我確實不是標題黨,接下來我將通過暴露隨着時間的推移,axios 在一些方面表現的力不從心,並推薦一個新的,相比 axios 更具現代化和創新性的請求工具給你,它就是 輕量級的請求策略庫 alova

接下來我們看看 Promise 式請求工具的弱點(axios)

  1. 與 React、Vue 等框架割裂

現在,React、Vue 等前端 UI 框架對於前端來說幾乎是不可缺少的,axios 無法和這些框架的狀態深度綁定,需要開發者自行維護它們,導致開發效率較低。

  1. 在性能方面毫無作爲

2023 年了,相比 10 年前的應用已經複雜了不知幾個數量級,在請求方面要求也越來越高,來保證頁面性能的要求,axios 在這方面毫無作爲,例如在頻繁地重複請求、同時發起多個相同請求等場景。

  1. 臃腫的體積

根據 bundlephobia 顯示,axios 的體積在壓縮狀態下有 11+kb,看下圖

鏈接在此

  1. 響應數據的 Ts 類型定義混亂

在使用 axios 時,你可能經常會這樣寫:

// 創建一個axios實例
const inst = axios.create({
  baseURL: 'https://example.com/'
})

// 在響應攔截器中返回data
inst.interceptors.response.use(response => {
  if (response.status === 200) {
    return response.data
  }
  throw new Error(response.status)
})

interface Resp {
  id: number
}
inst.get<Resp>('/xxx').then(result => {
  // result的類型總是爲axios.AxiosResponse<Resp>
  data.data
})
複製代碼

不知道是 axios 故意爲之還是忽略了,以上的發起的 GET 請求中,響應數據result的類型總是axios.AxiosResponse<Resp>的,但其實我們在響應攔截器中已經將response.data返回了,這導致響應數據類型混亂而被困擾。

在 alova 中是如何解決的呢?

alova 作爲一個更加現代化,更加適應複雜應用的請求方案,也給出了它更加優雅的解決方案。同時爲了降低給的學習成本,也保持了和 axios 相似的 api 設計,看起來就很熟悉有木有。

alova 讀作 “阿洛娃”,雖然和 axios 一樣都是以 a 開頭,以下兩個名稱需要注意區分哦!

與 UI 框架深度融合,自動管理請求相關數據

假設我們需要發起一個基本的數據獲取請求,以 vue 爲例,直接上對比代碼。

axios

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

<script setup>
import axios from 'axios';
import { ref, onMounted } from 'vue';

const loading = ref(false);
const error = ref(null);
const data = ref(null);

const requestData = () => {
  loading.value = true;
  axios.get('http://xxx/index').then(result => {
    data.value = result;
  }).catch(e => {
    error.value = e;
  }).finally(() => {
    loading.value = false;
  });
}
onMounted(requestData);
</script>
複製代碼

alova

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

<script setup>
import { createAlova, useRequest } from 'alova';

const pageData = createAlova({ baseURL: 'http://xxx' }).Get('/index');
const { loading, data, error } = useRequest(pageData);
</script>
複製代碼

在 axios 中需要自己創建對應的請求狀態並自行維護,而 alova 卻幫你接管了這項工作

開箱即用的高性能功能

傳統 Promise 式的請求工具主要定位於通過 Promise 的方式簡化請求,而提高性能可能是它們最不會考慮的一點,但作爲請求策略庫的 alova 中卻着重突出這一點,在 alova 中默認開啓了內存緩存和請求共享,這兩項可以極大地提高請求性能,提升用戶體驗的同時還能降低服務端壓力,讓我們來一一瞭解下它們吧。

內存緩存

內存模式就是在請求響應後將響應數據保存在本地內存中,當下次再發起相同請求時就會使用緩存數據,而不會再次發送請求,試想一下,當你在實現一個列表頁,點擊列表項可以進入詳情頁查看數據,你會想到用戶可能會頻繁在列表中點擊查看詳情,當詳情數據沒有變化時,如果每一次進入詳情頁都要請求一次未免也太浪費了,而且每次還需要用戶等待加載。在 alova 中你可以默認享受到這樣的待遇,以下展示下效果

請求共享

你可能遇到過這種情況,當一個請求發出但還未響應時,又發起了相同請求,就造成了請求浪費,或者重複提交問題,例如以下三種場景:

  1. 一個組件在創建時會獲取初始化數據,當一個頁面同時渲染多個此組件時,將會同時發出多次相同請求;
  2. 提交按鈕未被禁用,用戶點擊了多次提交按鈕;
  3. 當預加載還未完成時進入了預加載頁面,將會發起多次相同請求;

共享請求就是用來解決這些問題的,它是通過複用請求的方式來實現的,由於這種案例無法直觀展示,就不展示了,有興趣的小夥伴可以自行體驗體驗。

除此以外,自稱是請求策略庫的 alova 還提供了特定場景下的請求策略,我們將在下文中介紹,有興趣的小夥伴請繼續往下看。

輕量級的體積

壓縮狀態下的 alova 只有 4kb+,只有 axios 的 30%+,看下面截圖

鏈接在此

更加直觀的響應數據 TS 類型

在 axios 中,你想要定義響應數據的類型真是會讓人感到困惑,如果你是個 Typescript 的重度用戶,alova 可以給你提供完整的類型體驗,當你在請求處定義響應數據時的類型後,你可以在多處享受到它,會讓你感覺很清晰,我們來看看。

interface Resp {
  id: number
}
const pageData = createAlova({ baseURL: 'http://xxx' }).Get<Resp>('/index');
const {
  data,  // data的類型爲Resp
  loading, error, onSuccess, send
} = useRequest(pageData);
onSuccess(event => {
  // 在成功回調中獲取響應數據時,event.data的值類型也是Resp
  console.log(event.data);
});

const handleClick = async () => {
  // send函數可以手動再次發送請求,它將可以接收到響應數據,它的值類型還是Resp
  const data = await send();
}
複製代碼

至此,相比傳統的 Promise 式請求庫,你可能已經初步瞭解了 alova 的厲害。

但... 它的特性還遠不止於此!

alova 的其他特性

多 UI 框架同時支持

alova 同時支持 react、vue、svelte,無論你使用哪種 UI 框架,它都能滿足你。

與 axios 相似的 api 設計,用起來更簡單熟悉

alova 的請求信息構造幾乎和 axios 相同,我們來對比一下它們的 GET 和 POST 請求。

GET 請求

// axios
axios.get('/index', {
  // 設置請求頭
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // params參數
  params: {
    userId: 1
  }
});

// alova
const todoListGetter = alovaInstance.Get('/index', {
  // 設置請求頭
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // params參數
  params: {
    userId: 1
  }
});
複製代碼

POST 請求

// axios
axios.post('/login', {
  username: 'xxx',
  password: 'ppp'
}, {
  // 設置請求頭
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // params參數
  params: {
    userId: 1
  }
});

// alova
const loginPoster = alovaInstance.Post('/login', {
  username: 'xxx',
  password: 'ppp'
}, {
  // 設置請求頭
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  // params參數
  params: {
    userId: 1
  }
});
複製代碼

(請求策略)高性能分頁請求策略

自動維護分頁相關數據和狀態,並提供了常用的分頁數據操作能力,據官方介紹,可以讓列表頁流暢性提高 300%,編碼難度降低 50%,以下是官方提供的示例,有興趣的同學可以去看看。

分頁列表示例

下拉加載示例

(請求策略)無感數據交互

這個在我看來,這個無感數據交互請求策略可謂是一大創舉,我把它理解爲更加可靠的樂觀更新,官網是這樣解釋的:

無感數據交互是指用戶在與應用進行交互時,無需等待即可立即展示相關內容,或者提交信息時也無需等待即可展示操作結果,就像和本地數據交互一樣,從而大幅提升應用的流暢性,它讓用戶感知不到數據傳輸帶來的卡頓。可以更高限度地降低網絡波動帶來的問題,你的應用在高延遲網絡甚至是斷網狀態下依然可用。

在我的體驗過程中,即使在弱網狀態下,也可以讓我感受到一種毫無延遲帶來的順暢感,你也來感受下吧。

據我瞭解,它使用以下技術:

  1. 持久化的請求隊列來保證請求的安全性和串聯性;
  2. 請求重試策略機制,來保證請求的順利完成;
  3. 虛擬響應數據(一個創新的概念),來作爲未響應時的數據佔位,以便在響應後定位它並替換爲實際數據。

關於無感數據交互更具體的可以在官網瞭解哦

數據預拉取

通過拉取數據的方式預先加載好數據並緩存在本地,當真正用到這部分數據時就可以命中緩存並直接顯示數據,這種方式也極大地提升了用戶體驗。

寫在最後

總之,alova 作爲一個新生代的請求工具,具有很大的潛力,你也想試用的話,可以點擊以下鏈接去了解。

alova 官網

alova 的 Github 地址

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://juejin.cn/post/7213923957824979000