GraphQL 仅在查询中请求特定字段时才获取

GraphQL only fetch if certain field is requested in query

一个非常基本的模式:

type Foo {
    id: String!
    name: String!
    createdAt: Date!
    bars: [Bar]
}

type Bar {
    id: String!
    name: String!
    fooId: String!
}

然后是我的 Resolver 映射:

Query: {
    foo: 
      async (
        _: any,
        { id }: { id: string }
      ) => {

        const { data: fooObj } = await httpRequest({
          url: `/api/foos/${id}`
        });

        const barsResponse = await httpRequest({
          url: `/api/bars/?fooId=${id}`
        });
        const response = {
          ...fooObj.foo,
          bars: barsResponse.data.bars
        };
        return response;
      }
 }

如果用户执行以下查询:

{
  foo(id: "123456"){
    bars {
      name
    }
  }
}

查询解析器正确获取并 returns 正确形状的正确数据,但是,运行 这个查询:

{
  foo(id: "123456"){
    name
  }
}

理想情况下不会执行第二次获取请求来获取 bars。如果查询包含 bars?

,我如何拆分查询解析器以便它只运行 Bars 提取

是的,将获取逻辑移动到 bars 的解析器中:

const resolvers = {
  Query: {
    foo: () => {...},
  },
  Foo: {
    bars: ({ id }) => {
      const { data: { bars } } = await httpRequest({
        url: `/api/bars/?fooId=${id}`
      })
      return bars
    },
  },
}

传递给每个解析器的第一个参数是父字段解析到的值。只要 Query.foo 的解析器内部返回的内容包括 idFoo.bars.

的解析器就可以使用它

除非请求该字段(并且父字段未解析为空),否则不会调用该字段的解析器。因此,仅当请求中存在该字段时,才会触发对 /api/bars 的调用。

如果您愿意,也可以继续获取根级别的所有内容。传递给解析器的第四个参数是一个 GraphQLResolveInfo 对象,它将包含有关请求的信息,包括请求了哪些字段。您可以解析此对象并让您的根解析器相应地运行。但是,对于像这样更简单的场景,那就太过分了。