在 GraphQL 中是不是可以在对象类型级别上使用解析器?

Posted

技术标签:

【中文标题】在 GraphQL 中是不是可以在对象类型级别上使用解析器?【英文标题】:In GraphQL is it possible to have resolvers on object type level?在 GraphQL 中是否可以在对象类型级别上使用解析器? 【发布时间】:2019-02-18 15:18:24 【问题描述】:

我们正在研究一个相当复杂的 GraphQL 架构,其中我们有多个属于各种微服务的对象类型,其中每个对象类型都有一个我们可以查询的自然 API 端点。因此,如果可以直接为某些对象类型定义特定的解析器,这样做会非常方便,如下所示:

const typeDefs = gql`
    type Query 
      getBook(bookId: ID!): BookPayload
    

    type BookPayload 
        book: Book
        userErrors: UserError
    

    type Book 
      id: ID!
      title: String
      author: String
    
`;

const resolvers = 
    Query: 
        getBook: (parent, args, context, info) => 
            return 
                book:  id: args.bookId 
        
    ,
    Book: (parent) =>   // this object type level resolver doesn't seem to work
        return 
            id: parent.id,
            ...fetchBookMetadata(parent.id)
        ;
    
;

我知道这是一个微不足道的例子,可能看起来有点过度设计,但当架构开始变得非常复杂时,它确实更有意义(至少对我们而言),到处都有数百个交叉引用。现在有什么好办法解决这个问题吗?

【问题讨论】:

【参考方案1】:

是的,您应该能够使用指令执行此操作或类似的操作,请查看:

https://www.apollographql.com/docs/graphql-tools/schema-directives.html#Fetching-data-from-a-REST-API

我将在此处逐字发布本文中的引文和示例。

假设您定义了一个对应于 REST 的对象类型 资源,并且您希望避免为 每个领域

const typeDefs = `
directive @rest(url: String) on FIELD_DEFINITION

type Query 
  people: [Person] @rest(url: "/api/v1/people")
`;

class RestDirective extends SchemaDirectiveVisitor 
  public visitFieldDefinition(field) 
    const  url  = this.args;
    field.resolve = () => fetch(url);
  

根据规范,GraphQL 执行引擎在选择集上运行,这些选择集被分解为各个字段。将检查每个字段的值或现有解析器。

似乎如果你定义了一个类似上面的指令,你不会改变这个基本行为,但你会拦截并添加一个额外的自定义步骤,以便在进一步解析之前执行。

也许使用自定义标量可以实现类似的效果,但这不适用于架构设计。

【讨论】:

我们已经成功实施了这个解决方案,而且效果很好!谢谢你的回答! 我已经发布了一个指令,它完全可以做到这一点github.com/gajus/graphql-lazyloader

以上是关于在 GraphQL 中是不是可以在对象类型级别上使用解析器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ME51n tcode 中的项目级别上使自定义字段可编辑?

在 GraphQL 中不能有带有嵌套字段的输入类型。错误:预期类型是 GraphQLInputType,但不是

如何在我的 GraphQL 中为对象中的对象列表定义类型

实现 GraphQL 和 Flutter

在 .graphql 文件中定义 GraphQL 对象类型不起作用

数组中类型为 graphql 对象的 GraphQL 字段