前端轮子千千万,现在又出来多一个,本文讨论了Axios的局限性,并推荐了一种新的、更具现代化和创新性的请求工具——alova。
一、Axios的局限性
-
与框架割裂
- 在React、Vue等前端UI框架不可或缺的今天,Axios无法和这些框架的状态深度绑定,需要开发者自行维护,导致开发效率较低。
-
性能方面不足
- 随着应用复杂度增加,Axios在处理频繁重复请求、同时发起多个相同请求等场景下性能不佳。例如在列表页点击查看详情时,未变化的数据每次进入详情页都请求一次是浪费且让用户等待。
-
体积臃肿
- 根据bundlephobia显示,Axios压缩状态下有11 + kb。
-
响应数据Ts类型定义混乱
- 在Axios中,创建实例并设置响应拦截器后,发起GET请求时,响应数据类型总是
axios.AxiosResponse<Resp>
,尽管在拦截器中已将response.data
返回,导致类型混乱。
- 在Axios中,创建实例并设置响应拦截器后,发起GET请求时,响应数据类型总是
二、alova的特点
-
与UI框架深度融合
- 以Vue为例,使用alova时,不需要像Axios那样自行创建请求状态并维护。在Vue中,使用
createAlova
创建请求信息,通过useRequest
获取相关状态(如loading
、data
、error
),alova帮开发者接管了这些工作。
- 以Vue为例,使用alova时,不需要像Axios那样自行创建请求状态并维护。在Vue中,使用
-
开箱即用的高性能功能
- 内存缓存:请求响应后将数据保存在本地内存,下次相同请求直接使用缓存数据,避免重复请求。例如在列表页点击详情时,相同数据可复用缓存,提高效率。
- 请求共享:解决多个相同请求同时发起的问题,如多个组件同时获取初始化数据、提交按钮多次点击、预加载未完成进入页面等情况,通过复用请求实现。
-
轻量级体积
- 压缩状态下只有4kb +,是Axios的30% +。
-
更加直观的响应数据Ts类型
- 在请求处定义响应数据类型后,在多处可享受清晰的类型体验。例如定义
Resp
接口后,通过createAlova
创建请求信息时指定类型,在useRequest
获取的数据、成功回调中的数据以及手动发送请求接收到的数据类型都为Resp
。
- 在请求处定义响应数据类型后,在多处可享受清晰的类型体验。例如定义
-
其他特性
- 多UI框架支持:同时支持React、Vue、Svelte。
- 与Axios相似的api设计:GET和POST请求的设置方式与Axios相似,如设置请求头和参数的方式基本相同。
- 高性能分页请求策略:自动维护分页相关数据和状态,提供常用分页数据操作能力,可提高列表页流畅性,降低编码难度。
- 无感数据交互:用户无需等待即可展示内容或操作结果,像和本地数据交互一样。使用持久化请求队列、请求重试策略和虚拟响应数据等技术,在弱网或断网状态下也可用。
- 数据预拉取:预先加载数据并缓存在本地,真正用到时可直接命中缓存显示,提升用户体验。
三、案例对比-Axios 的局限性
1. 与框架状态割裂
场景:在 Vue/React 中,当需要根据请求状态更新组件 UI 时,Axios 需手动维护 loading
、error
等状态,而 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 更简洁,无需手动管理加载状态。
七、总结对比表
特性 | Axios | Alova |
---|---|---|
框架集成 | 需手动维护状态 | 深度集成 Vue/React/Svelte |
性能优化 | 无内置优化 | 内存缓存、请求共享、分页策略 |
体积 | 14.4KB | 3.8KB |
TypeScript 支持 | 类型嵌套复杂 | 自动类型推导,零配置 |
无感交互 | 需手动实现 | 内置 unperceivable 策略 |
预拉取 | 需服务端渲染配合 | 原生支持 |
- 何时选择 Axios?
- 项目已深度依赖 Axios 生态(如结合 Axios 拦截器、Mock 工具)。
- 对请求策略无特殊需求,仅需基础 HTTP 功能。
- 团队熟悉 Promise 风格且无需高性能优化。
- 何时选择 Alova?
- 需要与 Vue/React/Svelte 状态深度绑定的现代化项目。
- 高频请求场景(如分页、实时搜索)需要性能优化。
- 追求极致的 TypeScript 类型体验和代码简洁性。
- 需要无感交互、预拉取等创新功能。
通过以上对比,可以看出 Alova 在现代前端开发中针对复杂场景提供了更优雅的解决方案,而 Axios 仍适合轻量级或传统项目。两者并非完全替代关系,而是根据实际需求选择最优方案。