如何在urql Exchange中实现缓存优先并延迟更新缓存的离线延迟请求
实现Cache-and-Network类型的urql Exchange(带延迟请求与离线支持)
核心思路
要实现这类Exchange,我们需要完成三个核心逻辑:
- 优先从缓存读取数据并立即返回
- 延迟1秒后发起网络请求,成功后更新缓存
- 离线状态下跳过网络请求,避免抛出错误影响用户体验
完整实现代码
import { Exchange, makeOperation, OperationResult } from '@urql/core'; import { delay, from, switchMap, catchError, of, concat } from 'rxjs'; export const cacheAndNetworkWithDelayExchange: Exchange = ({ forward, cache }) => { return ops$ => { return ops$.pipe( switchMap(operation => { // 1. 读取缓存数据,生成初始响应流 const cachedData = cache.readQuery(operation.query, operation.variables); const initialCacheResult$ = cachedData ? of(makeOperation(operation.kind, operation, { data: cachedData })) : of(); // 2. 延迟1秒后的网络请求处理流 const delayedNetworkRequest$ = from(Promise.resolve()).pipe( delay(1000), switchMap(() => { // 离线状态下直接跳过网络请求 if (!navigator.onLine) { return of(); } // 发起网络请求并处理结果 return forward(operation).pipe( switchMap((result: OperationResult) => { // 请求成功时更新缓存 if (result.data) { cache.writeQuery(operation.query, operation.variables, result.data); } return of(result); }), // 捕获网络错误,避免错误覆盖缓存结果 catchError(() => of()) ); }) ); // 合并流:先返回缓存结果,再返回网络请求结果 return concat(initialCacheResult$, delayedNetworkRequest$); }) ); }; };
代码细节解释
缓存读取与初始响应:
- 通过
cache.readQuery直接读取缓存中的查询数据 - 若缓存存在有效数据,生成包含缓存数据的响应流;否则生成空流,等待网络请求结果
- 通过
延迟网络请求处理:
- 用rxjs的
delay(1000)实现1秒延迟,避免立即发起网络请求 - 通过
navigator.onLine检测浏览器在线状态,离线时直接返回空流,不触发网络请求 - 网络请求成功后,调用
cache.writeQuery手动更新缓存,确保后续请求能获取最新数据
- 用rxjs的
流合并与错误处理:
- 使用
concat合并缓存流和网络流,保证先返回缓存数据,再返回网络更新后的结果 - 捕获网络请求错误并返回空流,避免错误提示覆盖已展示的缓存内容
- 使用
使用方式
在创建urql Client时,将这个Exchange添加到exchange数组中(顺序需保证它能拿到cache实例,并能转发请求到fetchExchange):
import { createClient, fetchExchange } from '@urql/core'; const client = createClient({ url: '/your-graphql-endpoint', exchanges: [ cacheAndNetworkWithDelayExchange, fetchExchange, ], });
注意事项
- 离线检测局限性:
navigator.onLine并非100%可靠(比如VPN断开但本地网络仍连通),若需更精准的离线检测,可结合自定义的网络状态监听逻辑 - 延迟时间调整:可根据业务需求修改
delay(1000)中的毫秒数 - 错误处理扩展:若需要在网络请求失败时提示用户,可在
catchError中添加自定义的错误处理逻辑,而非直接返回空流
内容的提问来源于stack exchange,提问作者AHOYAHOY
相关产品推荐
相关产品推荐

