我认为GraphQL解析器的工作方式缺少明显的东西。这是我的模式(可以有Place
的{{1}})的简化示例:
AdditionalInformation
以及相关的解析器:
import { ApolloServer, gql } from 'apollo-server';
const typeDefs = gql`
type Place {
name: String!
additionalInformation: AdditionalInformation
}
type AdditionalInformation {
foo: String
}
type Query {
places: [Place]
}
`;
当我执行基本查询时:
const resolvers = {
Query: {
places: () => {
return [{name: 'Barcelona'}];
}
},
AdditionalInformation: {
foo: () => 'bar'
}
};
const server = new ApolloServer({typeDefs, resolvers});
server.listen().then(({ url }) => {
console.log(`API server ready at ${url}`);
});
我总是以{
places {
name,
additionalInformation {
foo
}
}
}
作为null
:
additionalInformation
这是我的第一个GraphQL应用程序,但我仍然不明白为什么{
"data": {
"places": [
{
"name": "Barcelona",
"additionalInformation": null
}
]
}
}
解析器未自动执行的原因。有什么方法可以让GraphQL知道它必须启动吗?
我已经找到了解决方法,但是我觉得有些棘手:
AdditionalInformation
答案 0 :(得分:1)
让我们暂时假设additionalInformation
是标量,而不是对象类型:
type Place {
name: String!
additionalInformation: String
}
places
解析器返回的值为:
[{name: 'Barcelona'}]
如果要进行类似的查询...
query {
places {
name
additionalInformation
}
}
您期望additionalInformation
是什么?该值将为null,因为additionalInformation
解析器返回的Place
对象上没有places
属性。
即使我们将additionalInformation
设置为Object类型(例如AdditionalInformation
),结果也是相同的-additionalInformation
字段将解析为null。这是因为默认解析器(当您不为字段指定解析器功能时使用的解析器)只是在寻找与父对象的字段同名的属性。如果找不到该属性,则返回null。
您可能已经为AdditionalInformation
(foo
)上的字段指定了解析器,但是由于不需要,该解析器不会被解雇,因为整个additionalInformation
字段都为空,因此所有关联类型的任何字段的解析程序都将被跳过。
要了解为什么这是理想的行为,请想象一下不同的模式:
type Article {
title: String!
content: String!
image: Image
}
type Image {
url: String!
copyright: String!
}
type Query {
articles: [Article!]!
}
我们有一个数据库,其中有一个articles
表和一个images
表作为我们的数据层。文章可能有也可能没有与之相关的图像。我的解析器可能看起来像这样:
const resolvers = {
Query: {
articles: () => db.getArticlesWithImages()
}
Image: {
copyright: (image) => `©${image.year} ${image.author}`
}
}
比方说,我们的呼叫getArticlesWithImages
解析为一篇没有图片的文章:
[{title:'Foo',内容:'All about foos'}]
作为API的使用者,我要求:
query {
articles {
title
content
image
}
}
image
字段是可选的。如果返回带有空image
字段的article对象,则说明数据库中没有关联的图像。作为前端客户端,我知道不渲染任何图像。
如果GraphQL返回image
的值,该怎么办?显然,我们的解析器将中断,因为不会传递任何父值。而且,但是,作为API的使用者,我现在必须解析image
的内容,并以某种方式确定图像是否实际上与文章相关联,我应该对此做些什么。
正如您已经建议的,此处的解决方案是为additionalInfo
指定一个解析程序。您也可以简单地在您的places
解析器中返回该值,即:
return [{name: 'Barcelona', additionalInfo: {}}]
实际上,如果架构的形状与基础数据层的形状对齐,则在处理真实数据时不太可能会遇到此类问题。