← 中文资源

简体中文版本

用 DataLoader 缓存 GraphQL resolver

把 N+1 resolver 包进 DataLoader,在一请求内批量处理键,并缓存单请求结果使同键只取一次。

阅读英文原文

请求内批量

DataLoader 收集一个 tick 内所有 load 调用并发一次批量函数。50 条订单各自 load 用户变为一次 findMany 而非 50 次。

context.loaders = {
  user: new DataLoader(async (ids) => {
    const users = await db.users.findMany({ where: { id: { in: ids } } });
    return ids.map((id) => users.find((u) => u.id === id));
  }),
};

按请求缓存,不按进程

在每请求 context 中创建 loader。模块级 loader 跨请求缓存,会把某用户数据服务给另一用户。每请求缓存随请求消亡,正是所需。

orders: { user: (order, _, ctx) => ctx.loaders.user.load(order.userId) }

预期结果

50 条订单触发一次数据库查询,同键每请求只取一次,测试断言查询数恒为一。loader 每请求重建,缓存不跨用户泄漏。批量函数须按键序返回,含缺失行的 null,否则缓存不一致;更长 TTL 缓存需另设层级。