graphql - 使用 GraphQL 触发嵌套解析器
问题描述
我认为我在 GraphQL 解析器的工作方式中遗漏了一些明显的东西。这是我的架构的简化示例(Place
可以有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
:
{
"data": {
"places": [
{
"name": "Barcelona",
"additionalInformation": null
}
]
}
}
这是我的第一个 GraphQL 应用程序,我仍然不明白为什么AdditionalInformation
解析器没有自动执行。有什么方法可以让 GraphQL 知道它必须触发它吗?
我找到了这个解决方法,但我觉得它有点棘手:
Place: {
additionalInformation: () => { return {}; }
}}
解决方案
让我们暂时假设它additionalInformation
是一个标量,而不是一个对象类型:
type Place {
name: String!
additionalInformation: String
}
places
解析器返回的值为:
[{name: 'Barcelona'}]
如果您要进行类似的查询...
query {
places {
name
additionalInformation
}
}
你希望additionalInformation
是什么?它的值将为空,因为解析器返回的对象上没有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', content: 'All about foos' }]
作为 API 的使用者,我要求:
query {
articles {
title
content
image
}
}
该image
字段是可选的。如果我返回一个带有空image
字段的文章对象,我知道数据库中没有关联的图像。作为前端客户端,我知道不要渲染任何图像。
如果 GraphQL 返回一个值,会发生image
什么?显然,我们的解析器会中断,因为它不会传递任何类型的父值。此外,然而,作为 API 的使用者,我现在必须解析内容image
并以某种方式确定图像是否实际上与文章相关联,我应该对它做些什么。
TLDR;
正如您已经建议的那样,这里的解决方案是为additionalInfo
. 您也可以简单地在places
解析器中返回该值,即:
return [{name: 'Barcelona', additionalInfo: {}}]
实际上,如果架构的形状与底层数据层的形状一致,那么在处理真实数据时就不太可能遇到此类问题。
推荐阅读
- django - django如何加载url但留在同一页面
- javascript - opencart 2.0.3.1 数量加减NaN错误
- r - 从 TOC 抑制 R Markdown 标题
- three.js - 如何在 aframe/三个 js 中渲染成本更低的球体?
- asp.net - Azure Application Insights 中报告的 window.onerror 中的无效字符;ASP.Net 网络应用程序
- python - 如何使用 numpy genfromtxt 读取固定宽度的混合格式文件?
- javascript - Dicsord.js 服务器信息
- python - Python 类在 Google Colaboratory 上表现异常
- html - HTML 中的图像在除法之外保持垂直堆叠
- laravel - 如何以格式化的方式打印此集合?