Apollo GraphQL:如何判断useQuery/useLazyQuery数据来自网络还是缓存?
在Apollo GraphQL中区分useQuery/useLazyQuery的数据来源(网络/缓存)
现状说明
目前Web端Apollo Client的useQuery或useLazyQuery默认返回结果里,没有像Apollo iOS端那样提供直接标识数据来源的字段,需要通过间接方案实现判断。
可行替代方案
1. 结合fetchPolicy与加载状态追踪
通过配置不同的fetchPolicy,配合loading状态可以间接区分数据来源:
- 使用
cache-first(默认策略):若组件未进入loading状态就拿到数据,数据大概率来自缓存;若先出现loading再返回数据,则来自网络请求。 - 使用
network-only:所有返回数据必然来自网络,无需额外判断。 - 使用
cache-and-network:会先返回缓存数据(此时loading为true),网络请求完成后再返回最新数据(loading变为false),可通过返回时机和loading状态区分两次数据的来源。
示例代码:
const { loading, data } = useQuery(GET_DATA_QUERY, { fetchPolicy: 'cache-and-network' }); // 首次返回:data来自缓存,loading为true // 二次返回:data来自网络,loading为false
2. 自定义Apollo Link添加来源标记
通过自定义Apollo Link,在数据流转阶段为结果添加来源标识:
- 编写
afterware类型的Link,在缓存读取成功时给数据附加__source: 'cache'字段; - 网络请求返回时,给数据附加
__source: 'network'字段。
示例简化代码:
const sourceMarkLink = new ApolloLink((operation, forward) => { return forward(operation).map(response => { const isFromCache = operation.getContext().cacheHit; return { ...response, data: { ...response.data, __source: isFromCache ? 'cache' : 'network' } }; }); }); // 将自定义Link加入Apollo Client的链路中 const client = new ApolloClient({ link: from([sourceMarkLink, new HttpLink({ uri: '/graphql' })]), cache: new InMemoryCache() });
之后在组件中可通过data.__source直接判断数据来源。
3. 监听缓存更新事件
利用Apollo Client的cache.watch方法监听目标查询的缓存变化,结合初始加载状态区分:
- 初始加载时触发的缓存读取,对应数据标记为缓存来源;
- 后续网络请求触发的缓存更新,对应数据标记为网络来源。
内容的提问来源于stack exchange,提问作者bunkscene
相关产品推荐
相关产品推荐

