
airi 项目中的 VueUse useTimeoutPoll实现任务完成后再轮询的定时拉取方案【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi导读useTimeoutPoll是 VueUse 提供的一个轮询工具组合式函数composable其核心语义是上一次任务执行完毕之后才重新计时并触发下一次轮询从而天然避免异步任务积压与回调重入问题。在 airi 这类需要实时刷新聊天、认证令牌、模型供应商状态的多端应用Web / Capacitor / Electron见 apps 目录中它是构建可靠轮询逻辑的高频选择。读完本文你将掌握useTimeoutPoll的完整 API、选项语义、与useIntervalFn/useTimeoutFn的取舍以及它在仓库中的实际应用模式。一、函数定位一个等做完再等下轮的轮询器useTimeoutPoll归类于 VueUse 的 Utilities 类别官方对其行为的定义只有一句话Use timeout to poll something. It will trigger callback after last task is done用 timeout 去轮询某件事并且只在最后一次任务结束后才触发下一次回调。这句话点出了它与传统setInterval轮询的本质区别setInterval按固定周期触发回调不关心上一次回调是否执行完毕异步任务一旦超过周期就会产生回调堆叠callback stacking / reentrancy导致并发请求风暴或状态错乱useTimeoutPoll在内部把轮询实现为执行任务 → 等待任务完成 → 再起一个 timeout → 再次执行任务的链条每次只存在一个在途任务天然满足串行轮询的需求。从类型声明可以看出它的fn签名是() Awaitablevoid即允许传入async函数框架会await该函数返回的 Promise确认完成后才安排下一次调度。这正是它能等到上次任务结束的机制前提。二、API 签名与选项详解根据仓库内 useTimeoutPoll.md 中记录的 Type Declarations完整签名如下export interface UseTimeoutPollOptions { /** * Start the timer immediately * * default true */ immediate?: boolean /** * Execute the callback immediately after calling resume * * default false */ immediateCallback?: boolean } export declare function useTimeoutPoll( fn: () Awaitablevoid, interval: MaybeRefOrGetternumber, options?: UseTimeoutFnOptions, ): Pausable参数说明参数类型说明fn() Awaitablevoid每次轮询要执行的异步回调可返回 Promise框架会等待其 resolve 后再安排下一轮intervalMaybeRefOrGetternumber轮询间隔毫秒。既可以是普通数字也可以是ref/reactive值或 getter 函数意味着间隔可以被动态响应式地修改optionsUseTimeoutFnOptions选项对象见下表选项语义选项类型默认值行为immediatebooleantrue是否立即启动计时器。设为false时不会自动开始轮询需要手动调用resume()immediateCallbackbooleanfalse调用resume()时是否立即执行一次回调而不是等待一个完整间隔。适合恢复轮询时马上刷新一次数据的场景注意options类型标注为UseTimeoutFnOptions——这与同仓库 useTimeoutFn.md 中定义的选项接口一致。事实上useTimeoutPoll正是基于useTimeoutFn实现的每次任务结束后调用内部start()重新开启一个 timeout形成串行轮询的循环。返回值PausableuseTimeoutPoll返回的是Pausable接口包含三个成员isActive当前是否处于轮询激活状态只读响应式pause()暂停轮询。暂停后不会立即中断在途任务而是不再安排下一轮resume()恢复轮询。若设置了immediateCallback: true恢复时会立刻执行一次回调。三、基础用法串行拉取数据官方 Usage 示例展示了一个最典型的场景——串行轮询一个异步数据源import { useTimeoutPoll } from vueuse/core const count ref(0) async function fetchData() { await new Promise(resolve setTimeout(resolve, 1000)) count.value } // Only trigger after last fetch is done const { isActive, pause, resume } useTimeoutPoll(fetchData, 1000)执行时序拆解组件挂载后immediate默认为true立即执行第一次fetchData()fetchData需要约 1 秒完成期间不会有第二个回调触发任务 resolve 后框架再等待1000ms间隔然后执行第二轮如此往复直到pause()被调用或组件卸载时自动清理。如果改用setInterval(fetchData, 1000)当fetchData耗时超过 1 秒时新的调用会在旧的还没结束时再次发起造成并发执行与响应乱序。useTimeoutPoll通过任务完成再计时彻底规避了这个问题。四、进阶用法响应式间隔与恢复即刷新4.1 响应式轮询间隔interval参数支持MaybeRefOrGetternumber因此可以随业务状态动态调整轮询频率而无需重建整个轮询器import { useTimeoutPoll } from vueuse/core const pollingMs ref(3000) const { resume } useTimeoutPoll(async () { await refreshStatus() }, pollingMs) // 某些场景下需要更频繁刷新时直接修改 ref 即可 pollingMs.value 5004.2 延迟启动 恢复时立即刷新如果希望轮询在初始化时不立刻执行例如等待某个前置条件就绪可以关闭immediate而在条件满足后resume()时立刻抓一次最新数据则配合immediateCallbackconst { resume, pause, isActive } useTimeoutPoll(fetchData, 5000, { immediate: false, // 先不自动开始 immediateCallback: true, // resume() 时立即执行一次 }) // 用户登录成功后开始轮询且马上刷一次 watch(isLoggedIn, (v) { if (v) resume() else pause() })这种条件驱动 恢复即刷新的组合是管理后台仪表盘、在线状态同步等场景的常用写法。五、与相关工具函数的对比与取舍airi 仓库多个包都依赖vueuse/core见 packages/stage-ui/package.json 中的vueuse/core、vueuse/shared等 catalog 依赖实际代码中围绕定时/轮询存在一个工具族理解它们的差异有助于选型函数底层机制是否等待任务完成典型用途useTimeoutPoll任务完成后重启 timeout是串行轮询避免异步积压useIntervalFnsetInterval否周期固定触发心跳、固定频率轻量刷新useTimeoutFn单次setTimeout封装是执行一次一次性延迟任务如防抖式刷新useRafFnrequestAnimationFrame否逐帧动画、布局测量useIntervalsetInterval否响应式计数器一个直观的仓库实例是 packages/stage-layouts/src/composables/theme-color.ts它使用useIntervalFn(() {...}, 250, { immediate: false })以 250ms 的固定周期刷新theme-colormeta 标签并在页面不可见useDocumentVisibility检测到非 visible时直接return跳过。这里任务极轻读一次 computed style 并写一个属性不存在异步堆积风险因此固定间隔的useIntervalFn比串行的useTimeoutPoll更合适——这也印证了选型原则任务可能耗时或相互依赖时选useTimeoutPoll任务轻量且允许固定节奏时选useIntervalFn。六、仓库实战轮询在 airi 中的落地模式虽然仓库中未直接出现useTimeoutPoll调用但其串行轮询/受控轮询的设计思想在 airi 的 Vue 层被useIntervalFn、useTimeoutFn、useRafFn广泛实践可为你应用useTimeoutPoll提供直接参照。6.1 供应商周期性校验useIntervalFn 手动 resume在 packages/stage-ui/src/stores/providers/provider.ts 中startPeriodicRuntimeValidation为每个启用的模型供应商按各自的intervalMs建立校验循环const loop useIntervalFn(() { void useProviderStore().validateProvider(providerId, { force: true }) }, intervalMs, { immediate: false, immediateCallback: false }) loop.resume() providerRevalidationLoops.set(providerId, loop)这里有一个细节选项同时关闭了immediate与immediateCallback随后手动调用loop.resume()启动并通过providerRevalidationLoopsMap 保存句柄以便按需pause()。若把validateProvider换成可能耗时更长的异步任务且担心校验请求互相重叠把这里的useIntervalFn换成useTimeoutPoll即可获得校验完成才发起下一轮的串行语义——这正是useTimeoutPoll的典型替换场景。6.2 认证令牌刷新useTimeoutFn 一次性延迟packages/stage-ui/src/stores/auth.ts 从vueuse/core引入useTimeoutFn用于在令牌即将过期时安排一次性的延迟刷新动作。useTimeoutFn是useTimeoutPoll的单轮版本useTimeoutPoll内部就是每次任务完成后再次调用useTimeoutFn的 start理解useTimeoutFn的immediate/immediateCallback语义同样默认true/false见 useTimeoutFn.md即可完全掌握useTimeoutPoll的调度细节。6.3 按需轮询与任务完成思维useRafFn 示例packages/stage-ui/src/components/scenarios/chat/composables/use-virtualizer-scroll.ts 使用useRafFn(..., { immediate: false })并返回{ pause, resume }只有当存在待处理的滚动请求时才resume()任务完成后立即pause()。这与useTimeoutPoll的有需求才运转、无需求即停理念一致packages/stage-ui/src/components/scenarios/chat/composables/use-chat-history-top-fade.ts 用useRafFn把滚动、resize、虚拟列表变更合并到同一动画帧再读取布局避免每帧重复测量。这些模式共同说明airi 的定时逻辑普遍遵循最小化在途工作 显式暂停/恢复的纪律useTimeoutPoll正是该纪律在需要周期性拉取外部状态时的标准答案。七、使用注意事项组件卸载自动清理useTimeoutPoll基于 Vue 的effectScope/onScopeDispose机制在组件或 effect scope 销毁时自动清除内部 timer无需手动pause()pause()不中断在途任务正在执行的异步fn会跑完只是不再安排下一轮如需取消当前任务应在fn内部配合 AbortSignal 等机制自行处理避免在fn内抛出未捕获异常导致轮询中断异常会使当前 Promise 提前 reject轮询链随之停止建议在fn内 try/catch 并做兜底间隔过短且任务耗时长时useTimeoutPoll的实际周期 ≈ 任务耗时 interval如果对刷新频率有硬性上限要求需结合业务侧的超时控制响应式间隔变化interval为ref时修改会即时生效于后续轮询但不会重置当前在途的 timeout避免产生边界竞态。八、小结useTimeoutPoll以极小的 API 面一个函数 两个选项 一个Pausable返回值解决了轮询中最棘手的异步任务重入问题是串行轮询的标准实现。在本仓库语境下可将其视为useIntervalFn固定节奏与useTimeoutFn单次延迟之间的任务完成后继续折中方案airi 中供应商周期性校验provider.ts、主题色采样theme-color.ts等场景的既有轮询模式均可无缝迁移到useTimeoutPoll以获得更强的串行保证。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考