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

如何在Apollo Client的InMemoryCache中为匹配正则的数据设置最大缓存时间

核心疑问解答

你提到的自定义Token类型方案中,要触发缓存过期重新拉取,只需要在read函数中返回undefined即可:Apollo Client会判定字段缓存缺失,自动触发服务端请求获取最新值。


可选实现方案

方案1:自定义Token类型实现(最稳定,推荐可控场景使用)

通过read+merge字段策略组合可以实现完整的过期控制,完整代码示例如下:

// 全局存储token的写入时间,WeakMap支持自动垃圾回收不会额外占用内存
const tokenWriteTime = new WeakMap();
// 自定义过期时长,示例为5分钟
const TOKEN_EXPIRE_MS = 5 * 60 * 1000;

const cache = new InMemoryCache({
  typePolicies: {
    Token: {
      fields: {
        id: {
          // 写入缓存时触发,记录写入时间
          merge(existing, incoming) {
            tokenWriteTime.set(incoming, Date.now());
            return incoming;
          },
          // 读取缓存时触发,判断是否过期
          read(cachedVal) {
            if (!cachedVal) return undefined;
            const writeTime = tokenWriteTime.get(cachedVal);
            // 过期则返回undefined触发重拉,否则返回缓存值
            if (!writeTime || Date.now() - writeTime > TOKEN_EXPIRE_MS) {
              return undefined;
            }
            return cachedVal;
          }
        }
      }
    }
  }
});

方案2:全局字段读取钩子(适配未知字段名、正则匹配值的场景)

InMemoryCache支持全局默认类型策略,所有类型的所有字段读取都会触发该钩子,你可以在钩子中匹配值的正则实现过期控制:

const fieldWriteTime = new WeakMap();
const TOKEN_VALUE_REG = /^short-lived-token-.+/;
const TOKEN_EXPIRE_MS = 5 * 60 * 1000;

const cache = new InMemoryCache({
  typePolicies: {
    // 匹配所有GraphQL类型
    __default: {
      fields: {
        // 匹配类型下的所有字段
        __default: {
          merge(existing, incoming) {
            if (typeof incoming === 'string' && TOKEN_VALUE_REG.test(incoming)) {
              fieldWriteTime.set(incoming, Date.now());
            }
            return incoming;
          },
          read(cachedVal) {
            if (typeof cachedVal !== 'string' || !TOKEN_VALUE_REG.test(cachedVal)) {
              return cachedVal;
            }
            const writeTime = fieldWriteTime.get(cachedVal);
            if (!writeTime || Date.now() - writeTime > TOKEN_EXPIRE_MS) {
              return undefined;
            }
            return cachedVal;
          }
        }
      }
    }
  }
});

注意:该方案会对所有字段读取做正则校验,性能损耗极低,如果你的业务中token正则没有匹配冲突可以直接使用。

方案3:基于服务端@token指令实现(最精准,无正则误判风险)

配合Apollo Client的指令处理逻辑,在响应返回时标记所有带@token指令的字段,后续读取时做过期判断即可:

// 存储所有带@token指令的字段标识(格式为「类型名.字段名」避免同名字段冲突)
const tokenFields = new Set();
const fieldWriteTime = new Map();
const TOKEN_EXPIRE_MS = 5 * 60 * 1000;

// 新增Apollo Link层处理查询,收集token字段
const tokenDirectiveLink = new ApolloLink((operation, forward) => {
  // 遍历查询AST,收集所有带@token指令的字段
  operation.query.definitions.forEach(def => {
    def.selectionSet?.selections?.forEach(sel => {
      if (sel.directives?.some(d => d.name.value === 'token')) {
        const typeName = operation.query.definitions[0].operation === 'query' ? 'Query' : 'Mutation';
        tokenFields.add(`${typeName}.${sel.name.value}`);
      }
    });
  });
  return forward(operation);
});

// 缓存配置全局钩子
const cache = new InMemoryCache({
  typePolicies: {
    __default: {
      fields: {
        __default: {
          merge(existing, incoming, { typename, fieldName }) {
            const fieldKey = `${typename}.${fieldName}`;
            if (tokenFields.has(fieldKey)) {
              fieldWriteTime.set(fieldKey, Date.now());
            }
            return incoming;
          },
          read(cachedVal, { typename, fieldName }) {
            const fieldKey = `${typename}.${fieldName}`;
            if (!tokenFields.has(fieldKey)) return cachedVal;
            const writeTime = fieldWriteTime.get(fieldKey);
            if (!writeTime || Date.now() - writeTime > TOKEN_EXPIRE_MS) {
              return undefined;
            }
            return cachedVal;
          }
        }
      }
    }
  }
});

// 初始化Apollo Client时注入链路
const client = new ApolloClient({
  link: tokenDirectiveLink.concat(createHttpLink({ uri: '/graphql' })),
  cache
});

注意事项
  • 如果多个不同字段返回相同的token值,WeakMap的存储逻辑可以正常工作,不会互相影响
  • 若需要避免过期瞬间多个相同请求并发,可以加简单的请求防抖逻辑,同一字段同一时间只发起一次重拉请求
  • 返回undefined触发的重拉会自动合并到原查询中,不会产生额外的无效查询

内容的提问来源于stack exchange,提问作者light24bulbs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 04:06:00