Skip to content

请求策略 useAutoRequest ​

让请求自己保持新鲜:轮询,加上仪表盘真正需要的三种「用户回来了」信号(焦点 / 重连 / 可见性)。

ts
function useAutoRequest<TArgs extends readonly unknown[], TData>(
  method: StrategyMethod<TArgs, TData>,
  options?: UseAutoRequestOptions<TData>
): UseAutoRequestResult<TData, TArgs>;

选项 ​

ts
interface UseAutoRequestOptions<TData> extends UseRequestOptions<TData> {
  pollingInterval?: number;
  enableFocusRefresh?: boolean;
  enableReconnectRefresh?: boolean;
  refreshOnVisible?: boolean;
}
选项类型真实默认值说明
pollingIntervalnumber未设置(等价 0,即不轮询)轮询间隔(毫秒)。下一次只在本次落定之后才排期,所以后端比间隔更慢时排队长度是 1,而不是不断堆叠
enableFocusRefreshbooleanfalse窗口重新获得焦点时刷新(window 的 focus)
enableReconnectRefreshbooleanfalse网络恢复时刷新(window 的 online)
refreshOnVisiblebooleanfalse标签页重新可见时刷新(document 的 visibilitychange,只在 visibilityState !== "hidden" 时)
其余——继承 UseRequestOptions(initialData / resetOnSend / immediate / 公共选项)

返回 ​

返回类型说明
runningSnailStateRef<boolean>在 start() 与 stop() 之间为 true
start()() => void开始轮询并挂上刷新监听;同时立刻发一次请求(用 refresh(),因此沿用上一次的发送参数)
stop()() => void停止轮询并移除本 hook 注册的每一个监听器
refresh()() => Promise<TData>复用上一次发送的参数立即请求一次
dispose()() => voidstop() + 一个永久标记:dispose 之后 start() 被忽略
send(...args)(...args: TArgs) => Promise<TData>继承自 useRequest,可手动带参数发送
状态句柄StrategyState<TData>与 useRequest 相同

running 用的是同一个适配器:它和请求状态一样,从传入的那个 method 上解析该 server 的 stateAdapter({ adapter } 覆盖同样生效)。所以在 Vue server 上 running 也是 Ref<boolean>, 不会退化成普通盒子 —— 两者不可能跟踪到不同的响应式系统。

示例 ​

ts
import { useAutoRequest } from "@snail-js/api/strategies";
import { statsApi } from "./service";

const stats = useAutoRequest(statsApi.get, {
  pollingInterval: 5000,
  refreshOnVisible: true,
  enableReconnectRefresh: true
});

stats.start();
stats.running.value;    // true

// 组件卸载时:
stats.dispose();

诚实地说,它的边界 ​

  • stop() 是唯一的释放点:它同时停掉轮询定时器并移除所有监听器,所以卸载的视图不会再被一个 focus 处理器吊住。start() 会重新武装两者。
  • 刷新监听器在创建时就挂上,而不是在 start() 里 —— 一个唯一职责是「用户回来就刷新」的 hook 不应该还需要额外调用一次;只有轮询本身受 start() / stop() 控制。代价是:创建即注册, dispose() 之前它们一直有效。
  • 定时器在 Node 上会被 unref(),不会让进程或测试 worker 一直活着。
  • window / document 是惰性查找的,可能不存在,所以在 SSR 里创建这个 hook 是无害的(监听器 注册会安静地失败)。
  • immediate: true 等价于立刻 start()(而 useAutoRequest 内部固定给 useRequest 传 immediate: false,所以不会发两次)。
  • refresh() 在任何 send() 之前被调用时没有任何参数:方法声明的 @Params 无法满足时这一次 会失败 —— 与 immediate 的契约一致。
  • 轮询的失败已经写进 error 与 onError,并且被吞掉:一次失败的轮询不会变成 unhandled rejection, 也不会中断下一次排期。

没有 pollingInterval 时 start() 只发一次

pollingInterval 缺失或不是正数时 schedule() 直接返回:start() 仍然会立刻请求一次、仍然会挂上 你打开的那几个刷新监听,但不会有周期。这是刻意的(0 间隔会变成锤击循环)。

相关 ​

基于 MIT 许可发布