有一个新的前端请求的轮子?我该怎么选择。。。

266 阅读6分钟

前端轮子千千万,现在又出来多一个,本文讨论了Axios的局限性,并推荐了一种新的、更具现代化和创新性的请求工具——alova。

一、Axios的局限性

  1. ​与框架割裂​

    • 在React、Vue等前端UI框架不可或缺的今天,Axios无法和这些框架的状态深度绑定,需要开发者自行维护,导致开发效率较低。
  2. ​性能方面不足​

    • 随着应用复杂度增加,Axios在处理频繁重复请求、同时发起多个相同请求等场景下性能不佳。例如在列表页点击查看详情时,未变化的数据每次进入详情页都请求一次是浪费且让用户等待。
  3. ​体积臃肿​

    • 根据bundlephobia显示,Axios压缩状态下有11 + kb。
  4. ​响应数据Ts类型定义混乱​

    • 在Axios中,创建实例并设置响应拦截器后,发起GET请求时,响应数据类型总是axios.AxiosResponse<Resp>,尽管在拦截器中已将response.data返回,导致类型混乱。

二、alova的特点

  1. ​与UI框架深度融合​

    • 以Vue为例,使用alova时,不需要像Axios那样自行创建请求状态并维护。在Vue中,使用createAlova创建请求信息,通过useRequest获取相关状态(如loadingdataerror),alova帮开发者接管了这些工作。
  2. ​开箱即用的高性能功能​

    • ​内存缓存​​:请求响应后将数据保存在本地内存,下次相同请求直接使用缓存数据,避免重复请求。例如在列表页点击详情时,相同数据可复用缓存,提高效率。
    • ​请求共享​​:解决多个相同请求同时发起的问题,如多个组件同时获取初始化数据、提交按钮多次点击、预加载未完成进入页面等情况,通过复用请求实现。
  3. ​轻量级体积​

    • 压缩状态下只有4kb +,是Axios的30% +。
  4. ​更加直观的响应数据Ts类型​

    • 在请求处定义响应数据类型后,在多处可享受清晰的类型体验。例如定义Resp接口后,通过createAlova创建请求信息时指定类型,在useRequest获取的数据、成功回调中的数据以及手动发送请求接收到的数据类型都为Resp
  5. ​其他特性​

    • ​多UI框架支持​​:同时支持React、Vue、Svelte。
    • ​与Axios相似的api设计​​:GET和POST请求的设置方式与Axios相似,如设置请求头和参数的方式基本相同。
    • ​高性能分页请求策略​​:自动维护分页相关数据和状态,提供常用分页数据操作能力,可提高列表页流畅性,降低编码难度。
    • ​无感数据交互​​:用户无需等待即可展示内容或操作结果,像和本地数据交互一样。使用持久化请求队列、请求重试策略和虚拟响应数据等技术,在弱网或断网状态下也可用。
    • ​数据预拉取​​:预先加载数据并缓存在本地,真正用到时可直接命中缓存显示,提升用户体验。

三、案例对比-Axios 的局限性

1. ​​与框架状态割裂​

​场景​​:在 Vue/React 中,当需要根据请求状态更新组件 UI 时,Axios 需手动维护 loadingerror 等状态,而 Alova 直接与框架响应式系统集成。
​对比示例​​(Vue3):

<!-- Axios -->
<script setup>
import { ref } from 'vue';
const loading = ref(false);
const data = ref(null);

async function fetchData() {
  loading.value = true;
  try {
    data.value = await axios.get('/api/data');
  } catch (e) {
    console.error(e);
  } finally {
    loading.value = false;
  }
}
</script>

<!-- Alova -->
<script setup>
import { createAlova, useRequest } from 'alova/vue';

const { data, loading, error } = useRequest(
  createAlova().get('/api/data')
);
</script>

​问题​​:Axios 需要重复编写状态管理逻辑,而 Alova 通过 useRequest 自动注入状态,减少样板代码。


2. ​​性能问题(进阶场景)​

​场景​​:高频重复请求(如输入框实时搜索)或并发请求(如同时触发多个 API)。
​Axios 实现​​:需手动防抖或取消请求:

let cancelTokenSource;

function search(query) {
  if (cancelTokenSource) {
    cancelTokenSource.cancel('Canceled previous request');
  }
  cancelTokenSource = axios.CancelToken.source();
  
  axios.get('/search', {
    params: { q: query },
    cancelToken: cancelTokenSource.token
  });
}

​Alova 解决方案​​:内置请求共享(Share Requests)自动合并相同请求:

// 自动去重,仅发送最后一次请求
const searchRequest = createAlova().get('/search', { params: { q: $query } });

3. ​​体积问题(量化对比)​

​Bundlephobia 数据​​(2023年更新):

  • Axios:压缩后 ​​14.4KB​
  • Alova:压缩后 ​​3.8KB​​(约 Axios 的 26%)
    ​影响​​:在微前端、小程序等资源受限场景下,Alova 显著减少包体积。

四、Alova 的进阶特性

1. ​​高性能分页策略​

​场景​​:长列表分页加载时,传统方式需手动缓存页码和数据,Alova 自动管理分页状态。
​示例​​:

const paginator = createAlova()
  .get('/items', {
    params: { page: 1, perPage: 20 },
    strategy: 'pagination' // 启用分页策略
  });

// 自动处理加载状态、缓存、页码切换
const { items, loading, error, loadMore } = usePaginator(paginator);

​效果​​:自动跳过相同页码请求,支持无限滚动,减少冗余网络调用。


2. ​​无感数据交互(关键创新)​

​场景​​:弱网环境下,用户操作(如表单提交)需即时反馈,避免等待真实响应。
​传统实现​​:需手动实现乐观更新和错误回滚:

async function submitForm(data) {
  // 乐观更新 UI
  updateUI(data);
  
  try {
    await axios.post('/submit', data);
  } catch (e) {
    // 回滚 UI
    revertUI();
  }
}

​Alova 实现​​:通过虚拟响应(Virtual Response)自动处理:

const submitRequest = createAlova().post('/submit', data);

// 自动显示加载状态,失败时恢复原数据
const { send, data: responseData } = useRequest(submitRequest, {
  strategy: 'unperceivable' // 无感交互策略
});

3. ​​数据预拉取(Prerendering)​

​场景​​:SEO 或首屏性能优化,提前加载关键数据。
​Alova 预拉取​​:

// 在服务端预取数据(Node.js 环境)
import { prerender } from 'alova/server';

export async function getServerSideProps() {
  const data = await prerender(createAlova().get('/api/data'));
  return { props: { data } };
}

// 客户端自动使用预拉取数据
const { data } = useRequest(preloadedData);

五、TypeScript 高级类型用法

​场景​​:复杂接口嵌套类型自动推导。
​Axios 类型痛点​​:

interface ApiResponse {
  data: {
    user: {
      id: number;
      name: string;
    };
  };
  status: number;
}

axios.get<ApiResponse>('/api/user').then(res => {
  // res.data 的类型为 ApiResponse,需多层访问
  const id = res.data.data.user.id; 
});

​Alova 类型优化​​:

// 定义接口时直接指定嵌套类型
interface User {
  id: number;
  name: string;
}

// Alova 自动推导嵌套类型
const userRequest = createAlova().get<User>('/api/user');

// 使用时无需多层解构
const { data: user } = useRequest(userRequest); 
// user 类型为 User,直接访问 user.id

六、跨框架支持

​React 版本对比​​:

// Axios
function MyComponent() {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(null);

  useEffect(() => {
    setLoading(true);
    axios.get('/api/data')
      .then(setData)
      .finally(() => setLoading(false));
  }, []);

  return <div>{loading ? 'Loading...' : data}</div>;
}

// Alova
function MyComponent() {
  const { loading, data } = useRequest(
    createAlova().get('/api/data')
  );

  return <div>{loading ? 'Loading...' : data}</div>;
}

​优势​​:Alova 的 React Hook API 更简洁,无需手动管理加载状态。


七、总结对比表

特性AxiosAlova
​框架集成​需手动维护状态深度集成 Vue/React/Svelte
​性能优化​无内置优化内存缓存、请求共享、分页策略
​体积​14.4KB3.8KB
​TypeScript 支持​类型嵌套复杂自动类型推导,零配置
​无感交互​需手动实现内置 unperceivable 策略
​预拉取​需服务端渲染配合原生支持

  1. 何时选择 Axios?
  • 项目已深度依赖 Axios 生态(如结合 Axios 拦截器、Mock 工具)。
  • 对请求策略无特殊需求,仅需基础 HTTP 功能。
  • 团队熟悉 Promise 风格且无需高性能优化。

  1. 何时选择 Alova?
  • 需要与 Vue/React/Svelte 状态深度绑定的现代化项目。
  • 高频请求场景(如分页、实时搜索)需要性能优化。
  • 追求极致的 TypeScript 类型体验和代码简洁性。
  • 需要无感交互、预拉取等创新功能。

通过以上对比,可以看出 Alova 在现代前端开发中针对复杂场景提供了更优雅的解决方案,而 Axios 仍适合轻量级或传统项目。两者并非完全替代关系,而是根据实际需求选择最优方案。