我试图从一个突变中返回一个查询类型,在某些情况下我可以使它工作,但不能按我想要的方式工作。问题与使用的查询类型没有特别关系,因为我发现使用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}`);
});
突变
mutation mutateMe($mutationArg: String = "YoloMute !", $helloMsg: String = "Yolhello") {
someMutation(someArg: $mutationArg) {
status
query {
hello(msg: $helloMsg)
}
}
}
回复
{
"data": {
"someMutation": {
"status": "Mute Mute: YoloMute !",
"query": null
}
}
}
我不明白为什么未调用hello
解析器,而query
字段是null
。
status
字段已由someMutation
解析器正确填充,但是由于query
字段未解析,因此我希望GraphQL为该字段调用现有的解析器并且应以Query
类型调用。
我发现了其他在技术上可行但不令人满意的方法:
答案 0 :(得分:4)
此问题并非真正针对Query
类型,而是涉及您如何设置解析器。
状态字段由someMutation解析程序适当填充,但是由于查询字段未解析,因此我希望GraphQL为该字段调用现有的解析程序,该解析器存在并且应针对查询类型进行调用。
没有针对整个Query
类型或任何其他类型的解析器。解析程序仅适用于特定类型的各个字段。如果未为字段定义解析器,则GraphQL将默认在父对象上查找与该字段同名的属性,并返回该属性的值。
让我们遍历您的文档。根级字段为:
someMutation(someArg: $mutationArg)
父值是所有根级突变的根值。除非您使用自定义根值,否则通常将是一个空对象。如果您没有为someMutation
类型的Mutation
字段定义解析器,则GraphQL会在根值中查找名为someMutation
的属性,并返回该属性(即未定义,这将在响应中被强制为null)。不过,我们做有一个解析器,它返回:
{
status: `Mute Mute: ${args.someArg}`,
}
现在,让我们解决status
字段。我们的父对象是父字段的解析程序返回的结果。在这种情况下,上面的对象。我们在status
上没有用于MutationResponse
的解析器,因此GraphQL在父级上寻找status
属性-它找到一个并使用它。 status
具有标量类型,因此解析程序返回的任何值都将被强制转换为适当的标量值。
query
字段如何?同样,query
上的MutationResponse
字段没有解析器。但是,我们在父对象上也没有名为query
的属性。因此,所有GraphQL可以做的就是对该字段返回null。
尽管query
的返回类型是ObjectType
,但由于它解析为null
,因此不会触发该ObjectType上字段的任何解析器。返回null表示该对象不存在,因此我们无需费心解析该对象上的任何字段。想象一下,如果一个字段返回了一个User对象。如果返回null,则无需解析用户名。
那么...我们如何解决这个问题?有两种方法:
向query
的解析器返回的对象中添加someMutation
的属性,如下所示:
{
status: `Mute Mute: ${args.someArg}`,
query: {},
}
或者,为该字段添加解析器:
MutationResponse: {
query: () => {},
},
任何一种方法都将确保query
字段将解析为非空值(在这种情况下,只是一个空对象)。由于解析的值不是null
,返回类型是ObjectType
(在这种情况下为Query
),因此将触发该类型字段的现在解析器并且hello
将按预期解决。