Graphql/Apollo 错误输出有时数据:空有时数据:{ 函数:空}



我正在为我的 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;
} 

我想获得一致的输出,有人知道如何解决这个问题吗?

这实际上是预期行为。

在 u 中updateUserupdateCity之间的区别在于后者返回一个可为空的类型 (City),而前者返回一个非空类型(User!)。响应的差异来自于错误向上传播响应,直到它们命中可为空的字段。从规格:

如果在解析字段时抛出错误,则应将其视为字段返回 null,并且必须将错误添加到响应中的"错误"列表中。

如果解析字段的结果为 null(因为解析字段的函数返回 null 或因为发生了错误),并且该字段属于 Non-Null 类型,则会引发字段错误。必须将错误添加到响应中的"错误"列表中。

由于非 Null 类型字段不能为 null,因此字段错误将传播为由父字段处理。如果父字段可能为 null,则解析为 null,否则,如果它是 Non-Null 类型,则字段错误将进一步传播到其父字段。

换句话说,通过在字段解析期间引发错误,我们可以有效地将该字段解析为 null。但是当我们告诉 GraphQL 一个字段具有非空类型,并且该字段解析为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和字段c抛出的解析器,则响应如下:

架构 1

{
"data": {
"a": {
"b": {
"c": null
}
}
}
}

架构 2

{
"data": {
"a": {
"b": null
}
}
}

架构 3

{
"data": null
}
extend type Mutation {
updateUser(userInfo: UserInfo!): User!
}

找到了修复程序,要求用户是不必要的,删除感叹号解决了我的问题(嗯...不知何故)

更新用户(用户信息:用户信息!):用户

最新更新