Apollo GraphQL:未在突变子字段上调用解析器
Apollo GraphQL: Resolver not called on mutation subfield
我正在尝试 return 来自突变的查询类型,在某些情况下我可以使它工作,但不是我想要的方式。该问题与所使用的查询类型没有特别关系,因为我发现使用 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
类型调用。
我发现了其他在技术上可行但不令人满意的方法:
- 直接 return 查询类型有效:
https://codesandbox.io/s/ovr9zpwr7q
- 架构中的重复行
作品:https://codesandbox.io/s/l4yrqzmq6l
这个问题并不是真正特定于 Query
类型,而是涉及您如何设置解析器。
The status field is duly filled by the someMutation resolver, but as the query field is not resolved there I would expect GraphQL to call an existing resolver for this field, which exists and should be called for the Query type.
整个 Query
类型或任何其他类型都没有解析器。解析器仅适用于特定类型的各个字段。当没有为字段定义解析器时,GraphQL 将默认在父对象上查找与该字段同名的 属性,并将 return 的值 属性.
让我们浏览一下您的文档。根级字段是:
someMutation(someArg: $mutationArg)
父值是所有根级突变的根值。除非您使用自定义根值,否则这通常是一个空对象。如果您没有为 Mutation
类型的 someMutation
字段定义解析器,GraphQL 将在您的根值中查找名为 someMutation
的 属性 和 return 那(即未定义,在响应中将被强制为 null)。不过,我们 有一个解析器,它 returns:
{
status: `Mute Mute: ${args.someArg}`,
}
现在,让我们解析 status
字段。我们的父对象是 return 由父字段的解析器编辑的结果。在这种情况下,上面的对象。 MutationResponse
上的 status
没有解析器,因此 GraphQL 在父级上寻找 status
属性 —— 它会找到一个并使用它。 status
具有标量类型,因此解析器 return 的任何值都将被强制转换为适当的标量值。
query
字段呢?同样,我们没有 MutationResponse
上的 query
字段的解析器。但是,我们在父对象上也没有名为 query
的 属性。因此,GraphQL 所能做的就是 return 该字段为 null。
即使 query
的 return 类型是 ObjectType
,因为它解析为 null
,该 ObjectType 上字段的任何解析器都不会被触发。返回 null 意味着该对象不存在,因此我们无需费心解析其上的任何字段。想象一下,如果一个字段 returned 一个 User 对象。例如,如果它 return 为空,则无需解析用户名。
那么...我们如何解决这个问题?有两种方式:
为 query
添加一个 属性 到对象 return 由 someMutation
的解析器编辑,像这样:
{
status: `Mute Mute: ${args.someArg}`,
query: {},
}
或者,为字段添加解析器:
MutationResponse: {
query: () => {},
},
任何一种方式都将确保 query
字段将解析为非空值(在本例中,只是一个空对象)。因为解析的值不是 null
并且 return 类型是 ObjectType
(在本例中是 Query
), 现在 解析器对于该类型的字段将被触发并且 hello
将按预期解析。
我正在尝试 return 来自突变的查询类型,在某些情况下我可以使它工作,但不是我想要的方式。该问题与所使用的查询类型没有特别关系,因为我发现使用 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
类型调用。
我发现了其他在技术上可行但不令人满意的方法:
- 直接 return 查询类型有效: https://codesandbox.io/s/ovr9zpwr7q
- 架构中的重复行 作品:https://codesandbox.io/s/l4yrqzmq6l
这个问题并不是真正特定于 Query
类型,而是涉及您如何设置解析器。
The status field is duly filled by the someMutation resolver, but as the query field is not resolved there I would expect GraphQL to call an existing resolver for this field, which exists and should be called for the Query type.
整个 Query
类型或任何其他类型都没有解析器。解析器仅适用于特定类型的各个字段。当没有为字段定义解析器时,GraphQL 将默认在父对象上查找与该字段同名的 属性,并将 return 的值 属性.
让我们浏览一下您的文档。根级字段是:
someMutation(someArg: $mutationArg)
父值是所有根级突变的根值。除非您使用自定义根值,否则这通常是一个空对象。如果您没有为 Mutation
类型的 someMutation
字段定义解析器,GraphQL 将在您的根值中查找名为 someMutation
的 属性 和 return 那(即未定义,在响应中将被强制为 null)。不过,我们 有一个解析器,它 returns:
{
status: `Mute Mute: ${args.someArg}`,
}
现在,让我们解析 status
字段。我们的父对象是 return 由父字段的解析器编辑的结果。在这种情况下,上面的对象。 MutationResponse
上的 status
没有解析器,因此 GraphQL 在父级上寻找 status
属性 —— 它会找到一个并使用它。 status
具有标量类型,因此解析器 return 的任何值都将被强制转换为适当的标量值。
query
字段呢?同样,我们没有 MutationResponse
上的 query
字段的解析器。但是,我们在父对象上也没有名为 query
的 属性。因此,GraphQL 所能做的就是 return 该字段为 null。
即使 query
的 return 类型是 ObjectType
,因为它解析为 null
,该 ObjectType 上字段的任何解析器都不会被触发。返回 null 意味着该对象不存在,因此我们无需费心解析其上的任何字段。想象一下,如果一个字段 returned 一个 User 对象。例如,如果它 return 为空,则无需解析用户名。
那么...我们如何解决这个问题?有两种方式:
为 query
添加一个 属性 到对象 return 由 someMutation
的解析器编辑,像这样:
{
status: `Mute Mute: ${args.someArg}`,
query: {},
}
或者,为字段添加解析器:
MutationResponse: {
query: () => {},
},
任何一种方式都将确保 query
字段将解析为非空值(在本例中,只是一个空对象)。因为解析的值不是 null
并且 return 类型是 ObjectType
(在本例中是 Query
), 现在 解析器对于该类型的字段将被触发并且 hello
将按预期解析。