Skip to content

缓存不是全局真相 ​

服务端状态有来源、加载中、成功、失败、更新时间和失效规则。缓存只是对服务端状态的暂存,不会因为存在一个 store 就变成权威数据。

ts
type QueryState<T> =
  | { status: 'idle' }
  | { status: 'loading'; previous?: T }
  | { status: 'success'; data: T; fetchedAt: number }
  | { status: 'error'; error: Error; previous?: T };

刷新、重新聚焦窗口、用户修改数据和权限变化都可能让缓存失效。失效后可以重新请求,也可以在确认写入成功后局部更新;关键是写清楚哪一个事件使缓存不再可信。

练习 ​

为“用户资料”设计缓存键和失效事件。要求用户切换账号时不能看到上一个账号的资料,更新昵称成功后列表和详情不能长期显示不同结果。

核心机制与实现 ​

状态设计先区分本地 UI、跨组件共享、服务器缓存和 URL 状态;全局 store 不是默认答案。

围绕“缓存不是全局真相”先写出输入 → 中间状态 → 可观察结果,再实现最小闭环。不要把事件监听、异步请求、DOM 读取或 store 写入混在一个函数里;每个副作用都要有创建、完成、取消和清理路径。

js
type State = { filter: string; selectedId: string | null }
const initial: State = { filter: '', selectedId: null }
function reducer(state: State, action: Action): State {
  if (action.type === 'filter/changed') return { ...state, filter: action.value }
  return state
}

逐步运行:先只验证成功路径,再改变一个输入;记录时间顺序、对象身份、错误类型和最终可见状态。若环境不支持某个浏览器 API,要把静态协议验证和真实浏览器验证分开记录。

失败边界与变体 ​

  • 输入为空、重复、过期或非法时,不应静默覆盖有效状态。
  • 组件卸载、路由离开、标签页关闭或请求取消时,资源必须停止写入。
  • 跨文档、Shadow DOM、Worker、SSR 或多标签页会改变可见边界,不能沿用单页面直觉。
  • 需要持久化时记录 schema 版本和迁移失败策略;需要全局状态时先证明局部状态不足。

可运行实验与练习 ​

画出状态所有者、读者和写入者;测试刷新、回退、并发请求、错误恢复和持久化迁移,解释为何某个状态不应放进全局 store。

练习要求:实现一个最小版本,补一个失败测试,再给出一个替代方案及其适用条件。答案应包括实际输入序列、观察结果、修复原因和未覆盖的浏览器差异。

查看本节答案

用心记录每一步成长