node.js - Graphql/Apollo 错误有时输出 data: null 有时 data: { function: null}
问题描述
我正在为我的 graphql 设置测试。这样做时,我意识到有时错误情况下的数据对象会像这样输出:
{
errors: [...],
data: null
}
而有时 :
{
errors: [...],
data: {
updateCity: null
}
}
那些测试是关于突变的。这是两个代码的示例:
解析器案例1:
updateUser(parent, args, context, info) {
logger.debug('Mutation > updateUser resolver');
return userController.user.update.user(parent, args.userInfo, context, info);
},
模式案例1:
extend type Mutation {
updateUser(userInfo: UserInfo!): User!
}
控制器案例 1:
user: async (parent, args, context, info) => {
try {
logger.debug('User Controller : update User');
await controller.validate(args);
const userModel = new UserModel('member');
if (!(await userModel.findOne(args.id))) errorscb.userInputError('User does not exist');
let id = args.id;
let newArgs = args;
delete newArgs.id;
return userModel.updateById(id, newArgs);
} catch (e) {
logger.warn({ stack: e.stack, message: e.message });
throw e;
}
},
模式案例 2:
extend type Mutation {
updateCity(id: Int!, name: String, countryId: Int): City
}
解析器案例2:
updateCity(obj, args, context, info) {
logger.info('City > updateCity resolver');
return cityController.city.update.city(obj, args, context, info);
},
控制器案例 2:
city: async (parent, args, context, info) => {
try {
logger.info('City Controller : update city');
await controller.validate(args);
const cityModel = new CityModel('city');
if (!(await cityModel.findOne(args.id)))
errorscb.userInputError('City does not exist');
let id = args.id;
let newArgs = args;
delete newArgs.id;
return cityModel.updateById(id, newArgs);
} catch (e) {
logger.warn({ stack: e.stack, message: e.message });
throw e;
}
我想获得一致的输出,有人知道如何解决吗?
解决方案
这实际上是预期的行为。
updateUser
和你的区别在于updateCity
后者返回一个可空类型(City
),而前者返回一个非空类型( User!
)。响应的不同之处在于错误会在响应中传播,直到它们到达可为空的字段。从规格:
如果在解析字段时抛出错误,则应将其视为该字段返回 null,并且必须将错误添加到响应中的“错误”列表中。
如果解析字段的结果为 null(因为解析该字段的函数返回 null 或因为发生错误),并且该字段是 Non-Null 类型,则抛出字段错误。必须将错误添加到响应中的“错误”列表中。
...
由于 Non-Null 类型的字段不能为 null,因此字段错误被传播以由父字段处理。如果父字段可能为空,则它解析为空,否则如果它是非空类型,则字段错误会进一步传播到它的父字段。
换句话说,通过在字段解析期间抛出错误,我们有效地将该字段解析为空。但是当我们告诉 GraphQL 一个字段具有 Non-Null 类型,并且该字段解析为 时null
,GraphQL 不能返回带有null
值的字段(因为这会破坏模式的契约)。所以它使整个父字段为空。如果父字段也是不可为空的,则将该字段的父字段清空,依此类推……直到它到达可空字段或请求的根(data
字段)。
比较:模式 1
type Query {
a: A
}
type A {
b: B
}
type B {
c: String
}
模式 2
type Query {
a: A
}
type A {
b: B
}
type B {
c: String!
}
模式 3
type Query {
a: A!
}
type A {
b: B!
}
type B {
c: String!
}
如果我们请求字段c
和字段 throws 的解析器c
,则响应如下:
模式 1
{
"data": {
"a": {
"b": {
"c": null
}
}
}
}
模式 2
{
"data": {
"a": {
"b": null
}
}
}
模式 3
{
"data": null
}
推荐阅读
- excel - 根据行的类别将行移动到另一个工作表
- tensorflow - 如何将cnn模型的预测结果保存为json格式?
- javascript - 如何将 Javascript 导出的类转换为 Kotlin/JS?
- spring-cloud - 更改spring cloud gateway中调用的实际URL
- php - 为什么 PHPMailer 无法连接到我的 SMTP 服务器
- python - FileNotFoundError,但文件确实存在
- node.js - 为什么 nodejs async-await 在与 api 调用配对时会返回随机顺序?
- rust - 如何访问从链下工作人员发送到托盘的信息并将其发送回链 Substrate Pallet V2
- javascript - 如何通过单击将按钮中的值添加到文本框中?
- amazon-rds - Aurora MySQL 1.* 是否即将报废?