- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个graphql
/ apollo-server
/ graphql-yoga
端点。该端点公开从数据库(或REST端点或其他服务)返回的数据。
我知道我的数据源正在返回正确的数据-如果将调用结果记录到解析器中的数据源,则可以看到正在返回的数据。但是,我的GraphQL字段始终解析为null。
如果我使该字段为非空,则在响应中的errors
数组内会看到以下错误:
无法为不可为空的字段返回null
为什么GraphQL不返回数据?
最佳答案
您的一个或多个字段解析为null的常见原因有两个:1)返回解析器内部形状错误的数据;和2)没有正确使用Promises。
注意:如果您看到以下错误:
无法为不可为空的字段返回null
根本的问题是您的字段返回null。您仍然可以按照以下概述的步骤尝试解决此错误。
以下示例将引用此简单模式:
type Query {
post(id: ID): Post
posts: [Post]
}
type Post {
id: ID
title: String
body: String
}
data
对象的“形状”。形状是指对象具有的属性,以及这些属性的值是标量值,其他对象还是对象或标量的数组。
post
字段中,我们返回值
{ title: 'My First Post', bod: 'Hello World!' }
。如果我们不为
Post
类型的任何字段编写解析器,我们仍然可以请求
post
:
query {
post {
id
title
body
}
}
{
"data": {
"post" {
"id": null,
"title": "My First Post",
"body": null,
}
}
}
title
字段,因为默认解析器完成了繁重的工作-它看到在父字段的Object字段上有一个名为
title
的属性(在本例中为
post
字段解析为null,因为我们在
id
解析器中返回的对象没有
post
属性。由于输入错误,
id
字段也解析为null -我们有一个名为
body
的属性,而不是
bod
!
body
不是拼写错误,而是API或数据库实际返回的内容,我们总是可以为
bod
字段编写一个解析器以匹配我们的模式。例如:
body
(parent) => parent.bod
字段解析为字符串或数字,则
post
类型上的每个字段的默认解析器仍将尝试在父对象上查找适当命名的属性,不可避免地失败并返回null。如果字段具有对象类型,但在其解析程序中返回的对象不是对象(例如String或Array),则不会看到有关类型不匹配的任何错误,但该字段的子字段将不可避免地解析为null。
Post
查询编写解析器,则可能会从其他端点获取代码,如下所示:
function post (root, args) {
// axios
return axios.get(`http://SOME_URL/posts/${args.id}`)
.then(res => res.data);
// fetch
return fetch(`http://SOME_URL/posts/${args.id}`)
.then(res => res.json());
// request-promise-native
return request({
uri: `http://SOME_URL/posts/${args.id}`,
json: true
});
}
post
字段的类型为
post
,因此我们的解析器应返回具有
Post
,
id
和
title
之类的属性的对象。如果这是我们的API返回的结果,那么我们都准备就绪。但是,通常将响应实际上是包含其他元数据的对象。因此,我们实际上从端点返回的对象可能看起来像这样:
{
"status": 200,
"result": {
"id": 1,
"title": "My First Post",
"body": "Hello world!"
},
}
body
,
id
和
title
属性。我们的解析器不需要执行以下操作:
function post (root, args) {
// axios
return axios.get(`http://SOME_URL/posts/${args.id}`)
.then(res => res.data.result);
// fetch
return fetch(`http://SOME_URL/posts/${args.id}`)
.then(res => res.json())
.then(data => data.result);
// request-promise-native
return request({
uri: `http://SOME_URL/posts/${args.id}`,
json: true
})
.then(res => res.result);
}
body
对象,该对象包含
Result
,
rows
,
fields
和
rowCount
之类的属性。您需要先从此响应中提取适当的数据,然后再将其返回到解析器中。
function post(root, args, context) {
return context.Post.find({ where: { id: args.id } })
}
command
是我们通过上下文注入的某种模型。如果使用的是
Post
,则可以调用
sequelize
。
findAll
和
mongoose
具有
typeorm
。这些方法的共同之处在于,尽管它们允许我们指定
find
条件,但它们返回的Promise仍然解析为数组而不是单个对象。虽然数据库中可能只有一个帖子具有特定ID,但是当您调用这些方法之一时,它仍包裹在数组中。因为数组仍然是对象,所以GraphQL不会将
WHERE
字段解析为null。但这会将所有子字段解析为null,因为它将无法在数组上找到适当命名的属性。
function post(root, args, context) {
return context.Post.find({ where: { id: args.id } })
.then(posts => posts[0])
}
post
),该方法将显式地仅从数据库返回一行(如果不存在,则返回null)。
function post(root, args, context) {
return context.Post.findOne({ where: { id: args.id } })
}
findOne
和
INSERT
调用的特别说明:我们通常希望插入或更新行或模型实例的方法返回插入或更新的行。他们经常这样做,但是有些方法却没有。例如,
UPDATE
的
sequelize
方法解析为布尔值,或者是加高后的记录和布尔值的元组(如果
upsert
选项设置为true)。
returning
的
mongoose
解析为具有
findOneAndUpdate
属性的对象,其中包含修改后的行。在将结果返回到解析器之前,请查阅您的ORM文档并适当地分析结果。
value
字段的类型是
posts
的
List
,这意味着其解析器需要返回对象数组(或解析为一个的Promise)。我们可能会这样获取帖子:
function posts (root, args) {
return fetch('http://SOME_URL/posts')
.then(res => res.json())
}
{
"count": 10,
"next": "http://SOME_URL/posts/?page=2",
"previous": null,
"results": [
{
"id": 1,
"title": "My First Post",
"body" "Hello World!"
},
...
]
}
function posts (root, args) {
return fetch('http://SOME_URL/posts')
.then(res => res.json())
.then(data => data.results)
}
Post
),也可以返回将解析为该值的Promise。对于具有
{ id: 1, title: 'Hello!' }
类型的字段,您还可以返回一个Promises数组。如果Promise拒绝,则该字段将返回null,并且相应的错误将添加到响应中的
List
数组。如果字段具有对象类型,则Promise解析为的值将作为父值向下传递给任何子字段的解析器。
errors
函数。该函数的实现细节并不重要-只是返回Promise的函数,该函数将解析为post对象。
getPost
字段的有效解析器可能如下所示:
function post(root, args) {
return getPost(args.id)
}
post
返回一个Promise,我们返回该Promise。无论Promise决定解决什么,它将成为我们领域解决的价值。看起来不错!
function post(root, args) {
getPost(args.id)
}
getPosts
语句的JavaScript函数中,将隐式返回
return
。因此,我们的函数创建一个Promise,然后立即返回
undefined
,使GraphQL为该字段返回null。
undefined
返回的Promise拒绝,我们也不会在响应中列出任何错误-因为我们没有返回Promise,所以底层代码并不关心它是解决还是拒绝。实际上,如果Promise拒绝,您将在服务器控制台中看到
getPost
。
UnhandledPromiseRejectionWarning
。
return
的调用结果,因此您将解析器更改为如下所示:
function post(root, args) {
return getPost(args.id)
.then(post => {
console.log(post)
})
}
getPost
时,我们实际上是在使用Promise解析的值并返回一个新的Promise。您可以想到它类似于
then
,但Promises除外。
Array.map
可以返回一个值或另一个Promise。无论哪种情况,
then
内部返回的内容都“链接”到原始Promise上。可以通过使用多个
then
将多个Promise链接在一起。链中的每个Promise都是按顺序解决的,最终值就是有效地解析为原始Promise的值。
then
内未返回任何内容,因此Promise解析为
then
,GraphQL将其转换为null。要解决此问题,我们必须退回帖子:
function post(root, args) {
return getPost(args.id)
.then(post => {
console.log(post)
return post // <----
})
}
undefined
并返回正确的值来正确地链接它们。例如,如果需要在调用
then
之前调用其他两个异步函数(
getFoo
和
getBar
),则可以执行以下操作:
function post(root, args) {
return getFoo()
.then(foo => {
// Do something with foo
return getBar() // return next Promise in the chain
})
.then(bar => {
// Do something with bar
return getPost(args.id) // return next Promise in the chain
})
getPost
的
mongoose
方法:
function post(root, args) {
return Post.findOne({ where: { id: args.id } }, function (err, post) {
return post
})
findOne
不会返回Promise。它只是返回未定义。在此示例中,我们的回调将被调用,如果我们记录
Post.findOne
的值,我们将看到从数据库返回的任何内容。但是,因为我们没有使用Promise,所以GraphQL不会等待此回调完成-它使用返回值(未定义)并使用它。
post
支持开箱即用。那些不经常使用免费的“包装”库来添加此功能的库。使用GraphQL解析器时,应避免使用利用回调的方法,而应使用返回Promises的方法。
function post(root, args) {
return new Promise((resolve, reject) => {
Post.findOne({ where: { id: args.id } }, function (err, post) {
if (err) {
reject(err)
} else {
resolve(post)
}
})
})
关于graphql - 为什么GraphQL查询返回null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56468150/
最近开始学习oracle和sql。 在学习的过程中,我遇到了几个问题,我的 friend 在接受采访时被问到这些问题。 SELECT * FROM Employees WHERE NULL IS N
这个问题在这里已经有了答案: Can we subtract NULL pointers? (4 个回答) 关闭 2 个月前。 是否定义了NULL - NULL? (char *)NULL - (ch
是否有推荐的方法(根据 .net Framework 指南)检查 null,例如: if (value == null) {//code1} else {//code2} 或 if (value !=
我正在尝试将值插入数据库,但出现这样的错误任何人都可以告诉我为什么该值为空,如下所示: An exception occurred while executing 'INSERT INTO perso
这个问题在这里已经有了答案: String concatenation with a null seems to nullify the entire string - is that desire
您好,我正在 Android 联系人搜索模块中工作。我正在查询下方运行。 cur = context.getContentResolver().query(ContactsContract.Data.
下面的 SQL 表定义说明了从我的 MYSQL 数据库创建表的语句之一,该数据库是由我公司的前开发人员开发的。 DROP TABLE IF EXISTS `classifieds`.`category
我主要有应用程序开发背景。在编程语言中 variable == null或 variable != null有效。 当涉及到 SQL 时,以下查询不会给出任何语法错误,但也不会返回正确的结果。 sel
我在尝试检查某些元素是否为 NULL 时遇到段错误或不。任何人都可以帮忙吗? void addEdge(int i, int j) { if (i >= 0 && j > 0)
在 SQL 服务器中考虑到以下事实:Col1 和 Col2 包含数值和 NULL 值 SELECT COALESCE(Col1,Col2) 返回一个错误:“COALESCE 的至少一个参数必须是一个不
在 SQL 服务器中考虑到以下事实:Col1 和 Col2 包含数值和 NULL 值 SELECT COALESCE(Col1,Col2) 返回一个错误:“COALESCE 的至少一个参数必须是一个不
下面查询的关系代数表达式是什么?我找不到“Is Null”的表达式。 SELECT reader.name FROM reader LEFT JOIN book_borrow ON reader.ca
我正在尝试使用三元运算符来检查值是否为 null 并返回一个表达式或另一个。将此合并到 LINQ 表达式时,我遇到的是 LINQ 表达式的 Transact-SQL 转换试图执行“column = n
我在给定的代码中看到了以下行: select(0, (fd_set *) NULL, (fd_set *) NULL, (fd_set *) NULL, &timeout); http://linux
var re = /null/g; re.test('null null'); //> true re.test('null null'); //> true re.test('null null')
这个问题在这里已经有了答案: 关闭 13 年前。 我今天避开了一场关于数据库中空值的激烈辩论。 我的观点是 null 是未指定值的极好指示符。团队中有意见的其他每个人都认为零和空字符串是可行的方法。
由于此错误,我无法在模拟器中运行我的应用: Error:null value in entry: streamOutputFolder=null 或 gradle - Error:null value
我正在尝试在 Android 应用程序中创建电影数据库,但它返回错误。知道这意味着什么吗? public Cursor returnData() { return db.query(TABLE
我一直在检查浏览器中的日期函数以及运行时间 new Date (null, null, null); 在开发工具控制台中,它给出了有效的日期 Chrome v 61 回归 Sun Dec 31 189
为什么 NA==NULL 会导致 logical (0) 而不是 FALSE? 为什么 NULL==NULL 会导致 logical(0) 而不是 TRUE? 最佳答案 NULL 是一个“零长度”对象
我是一名优秀的程序员,十分优秀!