Apollo GraphQL:未在突变子字段上调用解析器

deb*_*0ch 3 apollo graphql graphql-js apollo-server

我试图从一个突变中返回一个查询类型,在某些情况下我可以使它工作,但不能按我想要的方式工作。该问题与所使用的查询类型没有特别关系,因为我发现使用以外的其他类型具有相同的行为Query

您可以在https://codesandbox.io/s/1z8kjy8m93上运行和修改此代码

服务器

const { ApolloServer, gql } = require("apollo-server");

const typeDefs = gql`
  type Query {
    hello(msg: String): String
  }

  type Mutation {
    someMutation(someArg: String): MutationResponse
  }

  type MutationResponse {
    query: Query
    status: String
  }
`;

const resolvers = {
  Query: {
    hello: (root, args, context) => {
      console.log("hello: args = ", args);
      return `${args.msg}, world !`;
    }
  },
  Mutation: {
    someMutation: (root, args, context) => {
      console.log("someMutation: args = ", args);
      return { status: `Mute Mute: ${args.someArg}` };
    }
  }
};

const server = new ApolloServer({
  typeDefs,
  resolvers
});

server.listen().then(({ url }) => {
  console.log(` Server ready at ${url}`);
});
Run Code Online (Sandbox Code Playgroud)

突变

mutation mutateMe($mutationArg: String = "YoloMute !", $helloMsg: String = "Yolhello") {
  someMutation(someArg: $mutationArg) {
    status
    query {
      hello(msg: $helloMsg)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

响应

{
  "data": {
    "someMutation": {
      "status": "Mute Mute: YoloMute !",
      "query": null
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么hello不调用解析器而query字段是null

status字段由someMutation解析程序适当填充,但是由于该query字段未解析,因此我希望GraphQL为该字段调用一个现有的解析程序,该解析程序存在并且应该为该Query类型调用。

我发现其他在技术上可行但不令人满意的方法:

Dan*_*den 5

这个问题并不是真正针对特定Query类型的,而是与您如何设置解析器有关。

status字段由someMutation解析程序适当填充,但是由于查询字段未解析,因此我希望GraphQL对该字段调用现有的解析程序,该解析器存在并且应针对Query类型进行调用。

没有用于整个Query类型或任何其他类型的解析器。解析程序仅适用于特定类型的各个字段。如果未为字段定义解析器,则GraphQL将默认在父对象上查找与该字段同名的属性,并返回该属性的值。

让我们浏览您的文档。根级别字段是:

someMutation(someArg: $mutationArg)

父值是所有根级突变的根值。除非您使用自定义根值,否则通常将是一个空对象。如果您没有为类型的someMutation字段定义解析器Mutation,则GraphQL会someMutation在根值中查找一个称为的属性,然后返回该属性(即未定义,在响应中将其强制为null)。但是,我们确实有一个解析器,它返回:

{
  status: `Mute Mute: ${args.someArg}`,
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们解决这个问题status。我们的父对象是父字段的解析程序返回的结果。在这种情况下,上面的对象。我们没有statuson的解析器MutationResponse,因此GraphQL status在父级上寻找一个属性-它找到一个并使用该属性。status具有标量类型,因此解析程序返回的任何值都将被强制转换为适当的标量值。

query领域呢?同样,我们query在上的字段没有解析器MutationResponse。但是,我们也没有query在父对象上调用的属性。因此,所有GraphQL可以做的就是对该字段返回null。

即使for的返回类型queryObjectType,因为它解析为null,所以不会触发该ObjectType上的字段的任何解析器。返回null表示该对象不存在,因此我们无需费心解析该对象上的任何字段。想象一下,如果一个字段返回了一个User对象。例如,如果返回null,则无需解析用户名。

那么...我们如何解决这个问题?有两种方法:

为的解析器query返回的对象添加一个属性someMutation,如下所示:

{
  status: `Mute Mute: ${args.someArg}`,
  query: {},
}
Run Code Online (Sandbox Code Playgroud)

或者,为该字段添加一个解析器:

MutationResponse: {
  query: () => {},
},
Run Code Online (Sandbox Code Playgroud)

两种方式都将确保该query字段将解析为非null值(在这种情况下,只是一个空对象)。因为解析的值不是null并且返回类型是ObjectType(在这种情况下为Query),所以现在将触发该类型字段的解析器,hello并将按预期解析。