微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

GraphQL:几个字段解析器

如何解决GraphQL:几个字段解析器

大家!

有没有人在 graphql 中遇到过这样的情况:你需要像这样用多个异步源解析多个字段?

type Entity {
  # ---- dataSource1
  fieldA: String
  fieldB: String
  # ---- dataSource2
  fieldC: String
  fieldD: Stirng
}

所以fieldA和fieldB需要通过dataSource1解析, 和 fieldC 和 fieldD - 来自 dataSource2

我找到了 2 个解决方案,但它对于 graphql 来说似乎很不自然,而且看起来像是 hack。

有谁知道更方便的方法解决它?感谢您的帮助!

附言字段需要在同一个字段级别解析;

一个 - 检查查询的 AST 中的 dataSource2 属性包括它的调用与否:

Query: {
  Entity: async (_,args,context,info) => {
    const result = {};
    
    if (hasArrts(info,SOURCE_ONE_ARGS)) {
      const data = await dataSource1.load(args);
      Object.assign(result,data);
    }
    if (hasArrts(info,SOURCE_TWO_ARGS)) {
      const data = await dataSource2.load(args);
      Object.assign(result,data);
    }
    
    return result;
  }
}

2nd - 是像这样使用 graphql/DataLoader 管理它(由于缓存和数据加载器中的承诺调度,这是可能的)

Query: {
  Entity: {
    fieldA: async (_,args) => {
      const { fieldA } = await dataSource1.load(args);
    
      return fieldA;
    },fieldB: async (_,args) => {
      const { fieldB } = await dataSource1.load(args);
    
      return fieldB;
    },fieldC: async (_,args) => {
      const { fieldC } = await dataSource2.load(args);
      
      return fieldC;
    },fieldD: async (_,args) => {
      const { fieldD } = await dataSource2.load(args);
      
      return fieldD;
    },},};

解决方法

“正确答案”(这里引用,因为这是我的意见)绝对是第 2 位。我用 GraphQL 教授的原则之一是,您永远不应该在客户端没有特别要求的服务器上进行工作为了。这意味着,如果客户端只要求来自 DataSource1 的字段 A 和 B,那么您将毫无理由地执行所有调用 DataSource2 的工作。

这里有一些额外的要点:

  1. 通常在这种情况下,“对象有一个真实来源”,以及“获取其他属性的额外服务”。真实源通常会被父解析器调用来拉取对象,而“额外服务”只会在需要“额外查找”的解析器中调用。

  2. 有些人将这种情况发挥到极致并ONLY use field-level resolvers

  3. 如果您确实按照那篇博文的建议去做,请注意不要像他那样使用“虚拟解析器”作为父解析器。它只是返回 { id: <id> } 而没有实际调用事实来源以确保对象确实存在。这意味着如果对象实际上不存在,您将返回一个具有 null 属性的对象,而不是将 null 作为对象返回(因为它实际上并不存在)存在)。

如果你接受所有这些,你可以有两种方式:

仅检查是否存在:

const resolver = {
  Query: {
    someEntity: async (_,args,context) => {
      // Super light-way check for existence without loading any fields
      const exists = dataSource1.exists(args.id);

      if (!exists) {
        return null;
      }
      return { id: args.id };
    },},Entity: {
    fieldA: async (_,args) => {
      const { fieldA } = await dataSource1.load(args);
    
      return fieldA;
    },fieldB: async (_,args) => {
      const { fieldB } = await dataSource1.load(args);
    
      return fieldB;
    },fieldC: async (_,args) => {
      const { fieldC } = await dataSource2.load(args);
      
      return fieldC;
    },fieldD: async (_,args) => {
      const { fieldD } = await dataSource2.load(args);
      
      return fieldD;
    },};

首先从真实来源加载:

const resolver = {
  Query: {
    someEntity: async (_,context) => {
      return datasource1.load(args.id);
    },Entity: {
    fieldC: async (_,};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。