一个让你爽歪歪的请求工具是怎样的
各位好,很久没出来发一发alova文章了,现在的alova已经更新到第3个大版本了,看这篇文章可能会让你对它有个全新的认识。
如果你之前了解过alova,那么大概率知道alova是一个轻量级的请求策略库,通过它的客户端请求hooks和缓存高效地处理前端数据请求。
而到今天,alova3在此基础上实现了更大的提升,它不只是在客户端中使用,现在还能在服务端环境下大放异彩,是一个全栈式的极致高效的请求工具集,其核心目标是帮助开发团队更高效地集成和调用API,并且完美兼容fetch、axios等HTTP客户端,以及react、vue、svelte等UI框架。
具体来说,alova3相比之前的版本,它带来了以下的大更新。
- 多级缓存:请求效率和减压利器。
- 全栈的请求策略:帮你大大减少请求代码。
- 更加现代化的OpenAPI工具:不仅可以自动生成请求代码,还能把api文档搬到编辑器中,交互式地调用api,打破过去的api集成流程。
这里我想郑重声明一下,由于ai大模型对alova知识学习的不足,现在网上充斥着各种ai编写的alova的错误使用的文章,建议大家前往alova官网了解alova的正确使用方法。
一、多级缓存
多级缓存机制可以为你的服务端应用提供最快的请求体验。你可以自由选择单级缓存还是多级缓存使用,它们运行机制如下:
graph TD
A[用户请求] --> B{检查L1缓存}
B -->|命中| C[返回数据]
B -->|未命中| D{检查L2缓存}
D -->|命中| E[更新L1缓存]
D -->|未命中| F[请求API接口]
F --> G[更新L2缓存]
E --> C
G --> E
C --> H[结束]
默认情况下,alova 的一级缓存是简单的 object 以 key-value 的方式缓存,而二级缓存在不同环境下的默认表现也不同,具体看下面。
客户端
在客户端环境下,一级缓存一般用于短时的请求数据缓存,例如几分钟或几秒钟的频繁请求相同数据带来的性能消耗,当你在写 todo 详情页的时候,你可能会想到用户会频繁在 todo 列表中点击查看详情,此时使用一级缓存可以大大提升效率,降低服务端压力。
// 对详情数据设置60秒的一级缓存
alovaInstance.Get('/todo/detail', {
params: {
id: 'xxx'
},
cacheFor: 60 * 1000, // 设置60秒的一级缓存
// ...
});
而二级缓存可用于一些枚举数据、节日等长期不变的请求为主,默认使用localStorage存储。
// 对枚举数据设置3天缓存时间
alovaInstance.Get('/config/enum', {
params: {
key: 'xxx'
},
cacheFor: {
mode: 'restore',
expire: 3 * 24 * 3600 * 1000 // 缓存3天时间
},
});
服务端
在服务端环境下,多级缓存机制特别适用于以下场景:
-
高访问频率和低延迟需求:例如热门新闻、商品详情,可以进一步减少网络开销,在网络不稳定时也保持更快的响应。
-
减轻下游服务器压力:例如有访问高峰期的服务,上层缓存可以有效减少对后端数据库和微服务的压力。
-
整合多个下游服务器的数据合并和处理:多个串行请求可能导致更长的响应时间,也可能因复杂的数据转换消耗性能,可将转换后的数据进行缓存。
-
API 速率限制和计费:天气预报服务 API 每小时更新一次天气信息,地理位置数据 API 等。
-
鉴权数据:用户token等数据缓存到内存中,避免频繁的鉴权操作。
-
请求速率限制等分布式数据:用户的请求次数限制等数据。
具体可以看这篇文章
以下是一个使用进程间内存共享适配器加 LRU cache 作为一级缓存,redis 作为二级缓存的示例:
const { createPSCAdapter, NodeSyncAdapter } = require('@alova/psc');
const { LRUCache } = require('lru-cache');
const RedisStorageAdapter = require('./adapter-redis');
function lRUCache(options = {}) {
const cache = new LRUCache(options);
return {
set(key, value) {
return cache.set(key, value);
},
get(key) {
return cache.get(key);
},
remove(key) {
return cache.delete(key);
},
clear() {
return cache.clear();
}
};
}
const alovaInstance = createAlova({
// ...
// 进程间共享缓存适配器
l1Cache: createPSCAdapter(
NodeSyncAdapter(),
lRUCache({
max: 1000,
ttl: 1000 * 60 * 10
})
),
// redis缓存适配器
l2Cache: new RedisStorageAdapter({
host: 'localhost',
port: 6379,
username: 'default',
password: 'my-top-secret',
db: 0
})
});
通过多级缓存机制,alova3能够实现:
- 响应时间减少80%+:通过内存缓存实现毫秒级响应
- 服务器负载降低60%+:减少不必要的API调用
- 离线体验优化:持久化缓存支持完整的离线功能
- 带宽节约:减少重复数据传输
这种多级缓存架构使得alova3特别适合需要高性能数据访问的现代Web应用,在微服务架构和分布式系统中也表现出色。
二、全栈的请求策略
服务端请求策略
alova3一个关键特性是引入了对服务端的完整支持,你不仅可以在nodejs、deno、bun等运行时中使用,还提供了独有的服务端请求策略,简称server hooks,它可以很方便地处理分布式的BFF、API网关、第三方token管理等,同时还有请求速率限制、请求重试、验证码发送与校验等模块,可以快速实现分布式的特定业务逻辑。
BFF、API网关、第三方token管理等,在这篇文章中有详细的介绍,这边我们来看看验证码发送校验模块的使用。
按照惯例,首先创建一个alova实例。
const { createAlova } = require('alova/server');
const RedisStorageAdapter = require('@alova/storage-redis');
const adapterFetch = require('alova/fetch');
export const alovaInstance = createAlova({
// ...
requestAdapter: adapterFetch(),
// redis缓存适配器
l2Cache: new RedisStorageAdapter({
host: 'localhost',
port: 6379,
username: 'default',
password: 'my-top-secret',
db: 0
})
});
然后再创建一个验证码提供者函数,并指定使用redis适配器作为缓存载体,以便实现分布式环境下的使用。
const { createCaptchaProvider } = require('alova/server');
const { sendCaptcha, verifyCaptcha } = createCaptchaProvider({
store: alovaInstance.options.l2Cache
});
export sendCaptcha;
export verifyCaptcha;
第三步,再发送验证码,这里我们使用retry来实现重试,提高成功率。
// 创建一个发送验证码的method实例
const createCaptchaMethod = (code, key) = > alovaInstance.Post('/api/captcha', {
code,
email: key,
});
// 使用sendCaptcha hook包装createCaptchaMethod
const captchaMethod = sendCaptcha(createCaptchaMethod, {
key: 'xxx@xxx.com'
});
// 使用retry hook包装captchaMethod,并通过await发送请求并获取响应结果
const result = await retry(captchaMethod, {
retry: 3,
backoff: {
delay: 2000
}
});
最后一步,通过用户的提交来验证验证码。
const fakeCaptchaFromUserInput = '1234';
const isValid = await verifyCaptcha(fakeCaptchaFromUserInput, key);
console.log(isValid ? '验证通过' : '验证码错误');
客户端的请求策略
alova3的客户端请求策略与之前的版本大相径庭,依然提供了useRequest、useWatcher、usePagination等UI框架相关的hooks,在这里大家应该都很熟悉了,但不同的是,无论你使用react、vue还是svelte,这些hook都由统一的alova/client中导入。
import { useRequest } from 'alova/client';
const { data, loading, error, send } = useRequest(alovaInstance.Get('/todo/list'));
全栈框架nuxt支持
虽然在之前的版本中,alova已经支持在next、nuxt、svelitekit等SSR框架中使用,不过在alova3中,提供了一个专门适配nuxt的statesHook,可以在使用useRequest、useWatcher等几乎所有的hooks时不仅可以同步两端的数据,像内置的useFetch一样避免在客户端重复请求,还可以同步例如Date,Error等以及自定义类型的数据,用法也非常简单,设置一下NuxtHook即可。
import { createAlova } from 'alova';
import NuxtHook from 'alova/nuxt';
export const alovaInstance = createAlova({
// ...
statesHook: NuxtHook({
nuxtApp: useNuxtApp // 必须指定useNuxtApp
})
});
三、工具链支持:更加现代化的OpenAPI工具
除了核心库的增强,alova3还提供了开发工具和vscode扩展来优化工作流。
如果你的项目支持openapi,这些开发工具可以基本消除API文档,让你直接在编辑器中查找接口、查看完整文档并交互式地快速插入接口的调用代码,很大程度地提升了开发效率和体验。
同时,你还可以完全控制openapi在前端生成的内容,例如过滤掉某些接口,新增、删除或修改某个接口的参数等,这些在openapi文件不够规范,或者有错误时非常有用,并且是其他openapi自动生成工具所不具备的。
一起来具体看看怎么回事。
快速查找和插入调用代码
自定义修改生成内容
在一般情况下,服务端的返回数据格式会外包一层,例如:
{
code: 0,
message: "success",
data: {
// ...
}
}
而此时我们希望生成的响应数据类型为response.data,你可以在alova配置文件中使用payloadModifier插件。
import { defineConfig } from '@alova/wormhole';
import { payloadModifier } from '@alova/wormhole/plugin';
export default defineConfig({
generator: [
{
// ...
plugin: [
payloadModifier([
{
scope: 'response',
handler: schema => schema.data
}
])
]
}
]
});
你也还可以通过handleApi实现完全的自定义,例如以下是一个修改tag的例子:
export default defineConfig({
generator: [
{
handleApi: apiDescription => {
if (apiDescription.url.includes('/user')) {
apiDescription.tags = ['userTag'];
}
return apiDescription;
}
}
]
});
边查边接入接口
使用alova的vscode扩展,你可以直接在编辑器中查找接口,并直接插入调用代码,不仅如此,接口的所有相关信息都可以直接在代码中查看,像这样。
弹框中能清楚的看到接口的描述信息、请求参数、响应参数等,你可以一边看着弹框中的参数,一边在代码中传参,这个点子太棒啦,再也不用在api文档和编辑器中来回切换,然后每次还要重新找对应信息了。
编辑器中的api文档
这个vscode扩展还提供了在编辑器中查看接口文档的功能,你可以直接在编辑的侧边栏中查看接口文档,就像这样。
也可以在代码中的调用代码上直接点击“view documentation”打开对应的接口文档,可以实现快速查看接口的描述信息、请求参数、响应参数等。
写在最后
到这里,你应该感受到了一点alova3的不同了吧,通过以上的方式让前端在接口集成方向很大程度地提升效率,无论你是前端开发者希望提升应用性能,还是后端工程师需要构建高效的API网关,亦或是全栈开发者追求统一的开发体验,alova3都能为你提供完整的支持。
如果觉得alova还不错,真诚希望你可以尝试体验一下,也可以给我们来一个免费的github stars。
访问alovajs的官网查看更多详细信息:alovajs官网。
有兴趣可以加入我们的交流社区,在第一时间获取到最新进展,也能直接和开发团队交流,提出你的想法和建议。
有任何问题,你可以加入以下群聊咨询,也可以在github 仓库中发布 Discussions,如果遇到问题,也请在github 的 issues中提交,我们会在最快的时间解决。