GraphQL:从兄弟解析器访问另一个解析器/字段输出
Posted
技术标签:
【中文标题】GraphQL:从兄弟解析器访问另一个解析器/字段输出【英文标题】:GraphQL: Accessing another resolver/field output from a sibling resolver 【发布时间】:2017-05-26 14:44:23 【问题描述】:需要帮助。假设我请求以下数据:
parent
obj1
value1
obj2
value2
并且我需要 value1 解析器中 value2 的结果进行计算。
想过在 value2 中返回一个 Promise 并以某种方式将其放入 value1 解析器中,但是如果 value2 解析器还没有运行呢?
有什么办法可以做到吗?
【问题讨论】:
你需要它做什么?这可能是您的 API 设计的问题。 我有一个从 neo4j 数据库中获取数据的大型架构。对于每个实体(比如说用户、项目/产品),我制作了一个密码查询块。在每个实体中都有一些基于数据的计算字段。例如我有“用户”实体,他的解析器从数据库中获取原始数据,并通过他的地址、年龄和其他参数计算“排名”。现在我有了一个项目/产品实体,它也有一个计算字段 - “价格”,它使用用户排名来计算最终价格。 好吧,如果某个东西属于User
,来自DB 或计算,它应该是User
上的一个属性,而不是它的兄弟。你总是可以在内部解析中获取父级的解析值。
【参考方案1】:
我的直接想法是你可以使用上下文来实现这样的事情。我想你可以有一个类似缓存的对象和一个事件发射器来解决竞争条件问题。
例如,假设我们有一些类
class CacheEmitter extends EventEmitter
constructor()
super();
this.cache = ;
get(key)
return new Promise((resolve, reject) =>
// If value2 resolver already ran.
if (this.cache[key])
return resolve(this.cache[key]);
// If value2 resolver has not already run.
this.on(key, (val) =>
resolve(val);
);
)
put(key, value)
this.cache[key] = value;
this.emit(key, value);
然后从你的解析器你可以做这样的事情。
value1Resolver: (parent, args, context, info) =>
return context.cacheEmitter.get('value2').then(val2 =>
doSomethingWithValue2();
);
value2Resolver: (parent, args, context, info) =>
return doSomethingToFetch().then(val =>
context.cacheEmitter.put('value2', val);
return val;
我还没有尝试过,但这似乎对我有用!如果你试一试,我很好奇,所以让我知道它是否有效。只是为了记账,您需要确保实例化“CacheEmitter”类并将其输入到顶层的 GraphQL 上下文中。
希望这会有所帮助:)
【讨论】:
谢谢,我喜欢这个主意...如果我走那条路,我仍然需要解决查询没有 value2 的情况,我可以调用解析器,但我需要以某种方式调用所有父解析器。也让我想到人们做了什么来确保一些解析器承诺不会挂起来自 graphql 的响应。再次感谢我会试一试 您如何在context
上设置cacheEmitter
?例如。在express-graphql
中,context
已设置为请求对象。
@mpais 我如何设置cacehEmitter
?是每个节点吗?【参考方案2】:
根据graphql-resolvers:“GraphQL 目前不支持一个字段依赖于另一个字段的解析结果”。使用 EventEmiter 似乎是一种非常不规范的实现方式。 graphql-tools 提供了帮助函数,允许您以多种方式组成解析器,这应该可以帮助您。
【讨论】:
您能否建议任何使用graphql-tools
实现相同目的的示例【参考方案3】:
如果您正在缓存不应造成任何性能问题的内容,您可以再次在 obj1 解析器中加载 obj2 的 value2。
【讨论】:
以上是关于GraphQL:从兄弟解析器访问另一个解析器/字段输出的主要内容,如果未能解决你的问题,请参考以下文章
具有多个嵌套解析器并将字段映射到参数的 GraphQL 查询