如何配置Apollo watchQuery缓存失效后的cache-first/cache-and-network重取
适配需求的实现方案
这个需求完全可以落地,不需要重写watchQuery的内置策略逻辑,现有生态有两种成熟实现可选,完全匹配你要的“优先返回缓存、仅按一天间隔后台重拉”的运行逻辑。
方案1:使用Apollo Client内置缓存TTL能力(推荐,无额外自定义代码)
你之前找不到相关配置的核心原因是,官方没有把“按拉取间隔控制重取”的逻辑做进通用fetchPolicy的参数里,而是把这类细粒度的缓存生命周期控制,拆到了InMemoryCache的配置层。
具体配置步骤:
- 初始化客户端的
InMemoryCache时,给这类极少更新的元数据类型单独配置缓存有效时长,比如设置为24小时对应的毫秒数 - 对应调用
watchQuery时,直接使用cache-first的fetchPolicy即可,运行逻辑完全贴合预期:- 只要缓存中存在对应数据,不管缓存是否已经过了有效时长,
watchQuery都会第一时间把缓存结果返回给UI,不会阻塞等待网络请求 - 触发查询流程时,缓存层会自动校验上次写入该缓存的时间戳:如果间隔已经超过24小时,会自动标记缓存为过期,在后台发起网络重取,拿到新数据后静默更新缓存,再把最新值推送给UI
- 如果缓存被主动失效(比如调用
evict接口清空),不管时间间隔多少,都会自动触发网络拉取
- 只要缓存中存在对应数据,不管缓存是否已经过了有效时长,
方案2:自定义薄拦截逻辑(适配低版本无内置TTL的场景)
如果使用的Apollo Client版本低于3.7,没有内置的缓存TTL能力,也不需要去改写内置的cache-and-network/cache-first策略的源码,只需要加一层极薄的拦截逻辑就能实现同样效果:
- 全局维护一个针对这类元数据查询的时间戳Map,key为查询的唯一标识(比如元数据的分类、查询参数组合),value为上次成功拉取该数据的时间戳
- 对这类元数据的查询做两层逻辑判断:
- 触发
watchQuery时,优先读取本地缓存,第一时间把缓存结果抛给订阅方 - 完成缓存读取之后,再判断是否要触发网络请求:如果距上次成功拉取的时间没到24小时,直接跳过网络请求;如果超过间隔,或者本地没有对应缓存,才发起网络拉取,拉取成功后更新时间戳、写入本地缓存
- 触发
需要避开的坑
不要使用network-only或者默认的cache-and-network策略作为基础:这两类策略要么会先等网络请求返回才给UI结果,要么不管间隔多少每次触发查询都打网络,既会造成UI加载延迟,也没法降低服务器负载,完全违背你的设计目标。
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

