如何解决GraphQL:几个字段解析器
大家!
有没有人在 graphql 中遇到过这样的情况:你需要像这样用多个异步源解析多个字段?
type Entity {
# ---- dataSource1
fieldA: String
fieldB: String
# ---- dataSource2
fieldC: String
fieldD: Stirng
}
所以fieldA和fieldB需要通过dataSource1解析, 和 fieldC 和 fieldD - 来自 dataSource2
我找到了 2 个解决方案,但它对于 graphql 来说似乎很不自然,而且看起来像是 hack。
附言字段需要在同一个字段级别解析;
第一个 - 检查查询的 AST 中的 dataSource2 属性并包括它的调用与否:
Query: {
Entity: async (_,args,context,info) => {
const result = {};
if (hasArrts(info,SOURCE_ONE_ARGS)) {
const data = await dataSource1.load(args);
Object.assign(result,data);
}
if (hasArrts(info,SOURCE_TWO_ARGS)) {
const data = await dataSource2.load(args);
Object.assign(result,data);
}
return result;
}
}
2nd - 是像这样使用 graphql/DataLoader 管理它(由于缓存和数据加载器中的承诺调度,这是可能的)
Query: {
Entity: {
fieldA: async (_,args) => {
const { fieldA } = await dataSource1.load(args);
return fieldA;
},fieldB: async (_,args) => {
const { fieldB } = await dataSource1.load(args);
return fieldB;
},fieldC: async (_,args) => {
const { fieldC } = await dataSource2.load(args);
return fieldC;
},fieldD: async (_,args) => {
const { fieldD } = await dataSource2.load(args);
return fieldD;
},},};
解决方法
“正确答案”(这里引用,因为这是我的意见)绝对是第 2 位。我用 GraphQL 教授的原则之一是,您永远不应该在客户端没有特别要求的服务器上进行工作为了。这意味着,如果客户端只要求来自 DataSource1 的字段 A 和 B,那么您将毫无理由地执行所有调用 DataSource2 的工作。
这里有一些额外的要点:
-
通常在这种情况下,“对象有一个真实来源”,以及“获取其他属性的额外服务”。真实源通常会被父解析器调用来拉取对象,而“额外服务”只会在需要“额外查找”的解析器中调用。
-
有些人将这种情况发挥到极致并ONLY use field-level resolvers。
-
如果您确实按照那篇博文的建议去做,请注意不要像他那样使用“虚拟解析器”作为父解析器。它只是返回
{ id: <id> }
而没有实际调用事实来源以确保对象确实存在。这意味着如果对象实际上不存在,您将返回一个具有null
属性的对象,而不是将null
作为对象返回(因为它实际上并不存在)存在)。
如果你接受所有这些,你可以有两种方式:
仅检查是否存在:
const resolver = {
Query: {
someEntity: async (_,args,context) => {
// Super light-way check for existence without loading any fields
const exists = dataSource1.exists(args.id);
if (!exists) {
return null;
}
return { id: args.id };
},},Entity: {
fieldA: async (_,args) => {
const { fieldA } = await dataSource1.load(args);
return fieldA;
},fieldB: async (_,args) => {
const { fieldB } = await dataSource1.load(args);
return fieldB;
},fieldC: async (_,args) => {
const { fieldC } = await dataSource2.load(args);
return fieldC;
},fieldD: async (_,args) => {
const { fieldD } = await dataSource2.load(args);
return fieldD;
},};
首先从真实来源加载:
const resolver = {
Query: {
someEntity: async (_,context) => {
return datasource1.load(args.id);
},Entity: {
fieldC: async (_,};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。