You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:52:05