withAddonGroup
withAddonGroup 让一个异步函数依据需要进行分组,每个分组状态独立还支持并发调用。

典型场景包括:
- 列表中每一项都有「确认 / 删除 / 提交」等操作
- 多个 item 同时触发相同 API,但需要各自独立的 loading / error / data
- 操作在语义上是“同一个”,但在 UI 上是“多个并行实例”
基本用法
ts
const {
confirm,
confirmGroup
} = useAsync('confirm', confirmApi, {
addons: [
withAddonGroup({
key: (args) => args[0], // 使用第一个参数作为分组 key
}),
],
})在模板中使用
vue
<template>
<div v-for="item in items" :key="item.id">
<button
:loading="confirmGroup[item.id]?.loading"
@click="confirm(item.id)"
>
{{ confirmGroup[item.id]?.loading ? '确认中...' : '确认' }}
</button>
</div>
</template>👉 每一个 item.id 都会自动关联一个独立的 confirmGroup[item.id],不需要为每一项单独封装异步逻辑,也不需要手动管理状态映射。
数据结构
{name}Group 是一个按 key 分组的响应式数据集合:
ts
confirmGroup[key]每个 {name}Group[key] 始终包含以下字段:
ts
type GroupType<M extends (...args: any[]) => any> = {
loading: boolean
error: any
arguments: Parameters<M> | undefined
argumentFirst: Parameters<M>['0'] | undefined
data: Awaited<ReturnType<M>> | undefined
dataExpired: boolean
}特点说明
{name}Group[key] 是按需生成的。如果某个 key 从未被调用过时,{name}Group[key] 为 undefined,因此访问时需要使用可选链 ?.
ts
// ✅ 正确
confirmGroup[item.id]?.loading
// ❌ 错误(key 可能尚未存在)
confirmGroup[item.id].loading要欺骗 ts
{name}Group包含所有key很困难,会造成类型与实现不一致,所以统一通过可选链访问
插件特性
1. 自动创建与同步
- 当异步函数被调用时,对应的
{name}Group[key]会自动创建 - 符合该分组的请求状态(loading / error / data)会自动同步到
{name}Group[key]
2. 自动处理竞态
- 竞态逻辑与未分组时的逻辑完全一致
- 无需额外配置即可避免竞态问题
进阶:内存释放
⚠️ 大多数场景不需要关心内存问题
因为组件卸载会自动卸载所有关联变量。只有在以下情况才建议考虑:
- 异步状态存在于全局或长生命周期组件中,且分组 key 会持续增长(例如长时间存在的分页、无限滚动页面)
- 你在写一些基础组件,可以统一处理,比如分页列表组件
- 你希望在「上下文切换」时,主动清理旧分组
此时,随着 key 数量增长,{name}Group 会随之增长。
分页场景
ts
const page = ref(1)
const { queryItem, itemGroup } = useAsyncData(
'item',
getItemApi,
{
addons: [
withAddonGroup({
key: (args) => args[0], // itemId
scope: () => page.value, // 当前页作为作用域
}),
],
}
)当 page 变化时:
- 上一个 page 下的所有
{name}Group[key]会被自动清理
scope不是用于区分请求,而是用于定义这些分组何时整体失效。
手动清理
ts
const {
confirm,
confirmGroup,
clearConfirmGroup,
} = useAsync(
'confirm',
confirmApi,
{
addons: [withAddonGroup({ key: (args) => args[0] })],
}
)ts
// 清理指定 key
clearConfirmGroup('item1')
// 清理全部 group
clearConfirmGroup()在请求未结束时清除,请求完成后会自动丢弃。
心智模型
关于内存释放,记住这两句话就够了:
- key:区分 并行调用
- scope:定义 这些调用的生命周期
如果不明确是否需要使用,那就不使用。只用 key,就已经覆盖了 90% 的使用场景。
其它
- 灵感来源:useRequest 并行请求