对于成功的传输,GraphQL 总是返回 HTTP 200;问题在响应体里报告,而不是状态码。一个响应有两个顶层键:data 和 errors,两者可以同时出现——这就是部分数据(partial data)。
部分数据 + errors 数组
如果某个字段的 resolver 抛出异常,该字段会变成 , 里会新增一条记录,但其他所有字段仍会正常解析。客户端拿到成功的部分,外加对失败部分的描述。
对于成功的传输,GraphQL 总是返回 HTTP 200;问题在响应体里报告,而不是状态码。一个响应有两个顶层键:data 和 errors,两者可以同时出现——这就是部分数据(partial data)。
如果某个字段的 resolver 抛出异常,该字段会变成 , 里会新增一条记录,但其他所有字段仍会正常解析。客户端拿到成功的部分,外加对失败部分的描述。
nullerrors{
"data": { "user": { "name": "Ada", "posts": null } },
"errors": [
{
"message": "Failed to load posts",
"path": ["user", "posts"], // 究竟是哪个字段失败了
"extensions": { "code": "DOWNSTREAM_TIMEOUT" }
}
]
}
extensions.code 字段携带一个机器可读的错误码,好让客户端据此分支处理。一个抛错的字段是只把自己置空、还是向上冒泡,取决于可空性:一个非空字段(posts: [Post!]!)出错时,会把它最近的可空 parent 置空。
import { GraphQLError } from "graphql";
const resolvers = {
Mutation: {
transfer: (_p, args, ctx) => {
if (!ctx.user) {
// 附上一个客户端可分支处理的稳定错误码;隐藏内部细节
throw new GraphQLError("Not authenticated", {
extensions: { code: "UNAUTHENTICATED" },
});
}
// ...
},
},
};
许多团队还会把预期内的错误(校验、"邮箱已被占用")通过 union/result 类型建模进 schema,把 errors 数组留给意料之外的失败——从而让正常路径的类型保持干净。
面试官会考察你是否知道错误位于响应体中并伴随部分 data、错误码属于 extensions,以及可空性控制错误冒泡的程度。把 GraphQL 错误和 HTTP 状态码混为一谈,是某人只用过 REST 的典型破绽。
一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠