Deepdive into Tanstack/React Query - 2.4 Query 实例与状态机
2.4 Query 实例与状态机
Query 类是 TanStack Query 中管理单个查询生命周期的核心实体。它封装了查询的状态、数据获取逻辑、观察者管理以及与缓存的交互。本节将深入分析 Query 类的实现细节。
2.4.1 Query 类结构与继承自 Removable
Query 继承自 Removable 基类,后者提供了垃圾回收(GC)调度的核心能力。
Removable 基类
源码解析: Removable 提供了基于 gcTime 的延迟移除机制。当 Query 没有观察者且处于空闲状态时,会在 gcTime 后被从缓存中移除。
Query 的 optionalRemove 实现
2.4.2 状态机:status 与 fetchStatus 双轨状态
TanStack Query 采用双轨状态模型,将查询状态分为两个独立维度:
QueryState 类型定义
双轨状态模型
Loading diagram...
| status | fetchStatus | 含义 |
| pending | idle | 初始状态,无数据,未请求 |
| pending | fetching | 首次加载中 |
| success | idle | 有数据,空闲 |
| success | fetching | 后台刷新中(有旧数据可展示) |
| error | idle | 请求失败,空闲 |
| error | fetching | 错误后重试中 |
| * | paused | 因网络离线而暂停 |
初始状态生成
2.4.3 #dispatch 与 Reducer 模式
Query 使用类似 Redux 的 dispatch/reducer 模式来管理状态变更,确保状态转换的可预测性。
Action 类型定义
Reducer 实现
源码解析:
- 纯函数 Reducer: 状态转换逻辑封装在纯函数中,易于理解和测试
- 批量通知: 使用
notifyManager.batch()确保状态更新后的通知被合并处理 - 双重通知: 先通知观察者(触发 UI 更新),再通知缓存(触发 DevTools 更新)
辅助状态函数
2.4.4 fetch 方法完整流程
fetch 方法是 Query 的核心,负责执行数据获取并管理整个请求生命周期。
流程图
Loading diagram...
2.4.5 观察者管理 (addObserver/removeObserver)
Query 维护了一个观察者列表,用于在状态变化时通知所有相关的 QueryObserver。
源码解析:
- GC 控制: 添加观察者时清除 GC 定时器,移除最后一个观察者时重新调度 GC
- 智能取消: 根据
#abortSignalConsumed判断是否需要取消请求- 如果
queryFn使用了signal(支持取消),则取消请求并回滚状态 - 如果
queryFn未使用signal(不支持取消),则只取消后续重试,让当前请求完成以便缓存结果
- 如果
其他观察者相关方法
2.4.6 总结
Query 类是 TanStack Query 的核心数据单元,其设计体现了以下关键思想:
- 双轨状态模型: 将"数据状态"(
status) 和"请求状态"(fetchStatus) 分离,提供更精细的状态表达 - Reducer 模式: 使用 dispatch/reducer 模式管理状态,确保状态转换的可预测性
- 智能 GC: 基于观察者数量动态调度垃圾回收
- 请求去重: 自动复用进行中的请求,避免重复请求
- 优雅取消: 根据 queryFn 是否支持取消来决定取消策略
Loading diagram...