繁体   English   中英

GraphQL:几个字段解析器

[英]GraphQL: several field resolver

每个人!

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

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

所以 fieldA 和 fieldB 需要由 dataSource1 解析,而 fieldC 和 fieldD - 由 dataSource2 解析

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

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

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

第一个 - 是检查查询的 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;
  }
}

第二 - 是像这样使用graphql / dataloader管理它(由于数据加载器中的缓存和promise调度,这是可能的)

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;
    },
  },
};

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

这里有一些额外的点:

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

  2. 有些人将其发挥到极致, 只使用字段级解析器

  3. 如果您确实按照该博客文章的建议进行操作,请注意不要像他那样使用“虚拟解析器”作为父解析器。 它只是返回{ id: <id> }而不实际调用事实源以确保 object 确实存在。 This means that if the object doesn't actually exist , you would return an object with null properties instead of returning the null as the object (since it doesn't actually exist).

如果你 go 这一切,你可以 go 两种方式:

仅检查是否存在:

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 (_, args, context) => {
      return datasource1.load(args.id);
    },
  },
  Entity: {
    fieldC: async (_, args) => {
      const { fieldC } = await dataSource2.load(args);
      
      return fieldC;
    },
    fieldD: async (_, args) => {
      const { fieldD } = await dataSource2.load(args);
      
      return fieldD;
    },
  },
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM