Gii*_*iZz 3 node.js graphql graphql-js apollo-server
我正在为我的 graphql 设置测试。在这样做的同时,我意识到有时错误情况下的数据对象输出如下:
{
errors: [...],
data: null
}
Run Code Online (Sandbox Code Playgroud)
有时 :
{
errors: [...],
data: {
updateCity: null
}
}
Run Code Online (Sandbox Code Playgroud)
这些测试是针对突变的。这是两个代码的示例:
解析器案例 1:
updateUser(parent, args, context, info) {
logger.debug('Mutation > updateUser resolver');
return userController.user.update.user(parent, args.userInfo, context, info);
},
Run Code Online (Sandbox Code Playgroud)
模式案例 1:
extend type Mutation {
updateUser(userInfo: UserInfo!): User!
}
Run Code Online (Sandbox Code Playgroud)
控制器案例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;
}
},
Run Code Online (Sandbox Code Playgroud)
模式案例 2:
extend type Mutation {
updateCity(id: Int!, name: String, countryId: Int): City
}
Run Code Online (Sandbox Code Playgroud)
解析器案例 2:
updateCity(obj, args, context, info) {
logger.info('City > updateCity resolver');
return cityController.city.update.city(obj, args, context, info);
},
Run Code Online (Sandbox Code Playgroud)
控制器案例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;
}
Run Code Online (Sandbox Code Playgroud)
我想获得一致的输出,有人知道如何解决这个问题吗?
这实际上是预期的行为。
\nupdateUseryour和your之间的区别updateCity在于,后者返回可空类型 ( City),而前者返回非空类型 ( User!)。响应中的差异来自以下事实:错误会向上传播响应,直到到达可为 null 的字段为止。从规格来看:
\n\n如果在解析字段时引发错误,则应将其视为该字段返回 null,并且必须将错误添加到响应中的“错误”列表中。
\n如果解析字段的结果为 null(因为解析字段的函数返回 null 或者因为发生错误),并且该字段属于 Non-Null 类型,则会引发字段错误。错误必须添加到响应中的“错误”列表中。
\n...
\n由于非空类型字段不能为空,因此字段错误将传播到父字段来处理。如果父字段可能为 null,则它解析为 null,否则如果它是非 Null 类型,则字段错误将进一步传播到它的\xe2\x80\x99s 父字段。
\n
换句话说,通过在字段解析期间抛出错误,我们可以有效地将该字段解析为 null。但是,当我们告诉 GraphQL 某个字段具有 Non-Null 类型,并且该字段解析为 时null,GraphQL 无法返回带有值的字段null(因为这会破坏模式的约定)。所以它使整个父字段为空。如果父字段也是不可为空的,则它会将该字段的父字段设为空,依此类推...直到它到达可为空的字段或请求的根(字段data)。
比较:架构 1
\ntype Query {\n a: A\n}\n\ntype A {\n b: B\n}\n\ntype B {\n c: String\n}\nRun Code Online (Sandbox Code Playgroud)\n图式2
\ntype Query {\n a: A\n}\n\ntype A {\n b: B\n}\n\ntype B {\n c: String!\n}\nRun Code Online (Sandbox Code Playgroud)\n图式3
\ntype Query {\n a: A!\n}\n\ntype A {\n b: B!\n}\n\ntype B {\n c: String!\n}\nRun Code Online (Sandbox Code Playgroud)\n如果我们请求字段c和字段抛出的解析器c,响应如下:
图式1
\n{\n "data": {\n "a": {\n "b": {\n "c": null\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n图式2
\n{\n "data": {\n "a": {\n "b": null\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n图式3
\n{\n "data": null\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
942 次 |
| 最近记录: |