为接口编写 Apollo 解析器
Posted
技术标签:
【中文标题】为接口编写 Apollo 解析器【英文标题】:Writing an Apollo resolver for an interface 【发布时间】:2018-11-03 02:58:18 【问题描述】:假设我有以下 typedef:
interface Node
id: ID!
type Foo implements Node
id: ID!
quantity: Int
type Bar implements Node
id: ID!
name: String
我发送的每个 ID,我都想以同样的方式处理。目前我需要一些解析器,例如:
// ...
Foo:
id: (root) => encodeId(root.id, root.type),
// ...
,
Bar:
id: (root) => encodeId(root.id, root.type),
// ...
,
// ...
由于许多类型实现了Node
,这会导致大量代码重复,并且开发人员很容易忘记编码 id 的正确方法,或者忘记将它们一起编码。
有没有办法做这样的事情?
// ...
Node:
__resolveType: (root) => root.type,
id: (root) => encodeId(root.id, root.type)
,
// ...
这样Foo
、Bar
和Node
的任何其他实现将继承id
解析器?
【问题讨论】:
【参考方案1】:对于仍然对这个问题感到困惑的人,您可以将makeExecutableSchema
中的inheritResolversFromInterfaces
标志设置为true
。
在这里找到它:https://github.com/apollographql/graphql-tools/issues/762#issuecomment-385591309
Apollo 文档在这里:https://www.apollographql.com/docs/apollo-server/api/apollo-server/#makeexecutableschema
【讨论】:
【参考方案2】:这是一个有趣的问题。我不确定接口的解析器是否会接受__resolveType
以外的任何内容。
我偶尔会遇到这样的问题,但我使用默认和组合解析器修复它。
例如,对于 Node,您可以使用以下默认解析器:
const defaultNodeIdResolver = (root) => encodeId(root.id, root.type)
const defaultNodeOtherFieldResolver = (root) => root /* do something */
const defaultNodeResolvers =
id: defaultNodeIdResolver,
otherField: defaultNodeOtherFieldResolver,
那么你可以按如下方式实现另一个:
// ...
Foo:
// use object spread
...defaultNodeResolvers,
// ...
,
Bar:
// pick a specific resolver
id: defaultNodeIdResolver,
// ...
,
Baz:
...defaultNodeResolvers,
// you can even "override"
id: (root) => root,
,
这也有助于将解析器逻辑与解析器定义分离。我建议随着项目的发展。您还可以在解析器组合中工作(请参阅https://www.apollographql.com/docs/graphql-tools/resolvers.html#graphql-resolvers)。
您只需要确保您可以访问对象传播。无论如何你应该。很有帮助。
【讨论】:
是的,这或多或少是我最终的结果。对于我的每个interface
s,我都有一个implementsXYZ
对象,其中包含我想要共享的解析器,并在实现它的每种类型上使用扩展运算符。以上是关于为接口编写 Apollo 解析器的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 apollo / graphql 实现节点查询解析器