轮询(Polling)
refetchInterval 使查询按定时器重新拉取。将其设为以毫秒为单位的数字,查询将在存在至少一个活跃观察者时每 N 毫秒执行一次:
1useQuery({2 queryKey: ['prices'],3 queryFn: fetchPrices,4 refetchInterval: 5 * 1000, // every 5 seconds5})轮询与 staleTime 相互独立。一个查询即使处于新鲜(fresh)状态,仍会按计划轮询;有关 staleTime 如何与其他重新拉取行为交互,请参阅 重要默认值。refetchInterval 始终基于自身的时钟触发,不受新鲜度影响。
根据查询状态动态调整轮询间隔
可传入一个函数而非固定数值,以根据当前查询状态计算轮询间隔。该函数接收 Query 对象,应返回以毫秒为单位的数值,或返回 false 以停止轮询:
1useQuery({2 queryKey: ['job', jobId],3 queryFn: () => fetchJobStatus(jobId),4 refetchInterval: (query) => {5 // Stop polling once the job finishes6 if (query.state.data?.status === 'complete') return false7 return 2 * 10008 },9})返回 false 将清除间隔定时器。若查询结果发生变化,导致该函数再次返回正数,则轮询将自动恢复。
后台轮询
默认情况下,当浏览器标签页失去焦点时,轮询会暂停。对于仪表盘类应用,或任何需要在用户切换至其他标签页时仍保持数据最新性的界面,可禁用该行为:
1useQuery({2 queryKey: ['portfolio'],3 queryFn: fetchPortfolio,4 refetchInterval: 30 * 1000,5 refetchIntervalInBackground: true,6})暂停轮询
向 refetchInterval 传入一个函数,并在其中闭包捕获组件状态,即可控制轮询的执行时机:
1useQuery({2 queryKey: ['prices', tokenAddress],3 queryFn: () => fetchPrice(tokenAddress),4 refetchInterval: () => {5 if (!tokenAddress || isPaused) return false6 return 15 * 10007 },8})支持离线状态的轮询
TanStack Query 通过监听浏览器的 online 和 offline 事件来检测网络连接状态。在这些事件无法可靠触发的环境中(例如 Electron、某些嵌入式 WebView),可设置 networkMode: 'always' 以跳过连接性检查:
1useQuery({2 queryKey: ['chainStatus'],3 queryFn: fetchChainStatus,4 refetchInterval: 10 * 1000,5 networkMode: 'always',6})有关网络模式的更多信息,请参阅 网络模式(Network Mode)。
关于去重的说明
每个 QueryObserver(即每个使用 useQuery 并配置了 refetchInterval 的组件)都运行自己的定时器。两个订阅相同查询键且均设置了 refetchInterval: 5 * 1000 的组件,各自都会每 5 秒触发一次定时器。真正被去重的是并发进行中的拉取请求:若两个定时器同时触发,则仅发出一个网络请求。定时器作用于观察者层级,而去重则发生在查询层级。