使用 GraphQL 代码生成器从解析器返回不完整的形状

Posted

技术标签:

【中文标题】使用 GraphQL 代码生成器从解析器返回不完整的形状【英文标题】:Return incomplete shapes from resolver with GraphQL Code Generator 【发布时间】:2021-01-30 22:34:44 【问题描述】:

我使用以下约定让解析器返回部分数据,并允许其他解析器完成缺失的字段:

type UserExtra 
  name: String!


type User 
  id: ID!
  email: String!
  extra: UserExtra!


type Query 
  user(id: ID!): User!
  users: [User!]!

const getUser = (id: string):  id: string, email: string, extra:  name: string  => fetchUser(id);

// `fetchUsers` only returns `id` and `email`, but not `extra`
const getUsers = ():  id: string, email: string [] => fetchUsers();

// we can use this function to fetch the extra field for a given user
const getUserExtra = (id: string):  name: string   => fetchUserExtra();

export default 
  Query: 
    user: (parent, args) => getUser(args.id),
    users: () => getUsers(),
  ,
  User: 
    // here we fetch the `extra` field anytime an `User` is requested
    // in real-life I would check if the query is requesting the `extra`
    // field or not, and only fetch the data if requested by the query
    extra: (parent) => 
      return getUserExtra(parent.id)
    ,
  

我遇到的问题是 GraphQL 代码生成器生成了一个 Resolver 类型,它期望 Query#users 返回完整的 User 形状,当然它不知道即使我返回一个部分来自Query#users 的形状,感谢User#extra 客户端最终将收到预期的形状。

在让 TS 满意的同时处理这种情况的最佳方法是什么?

【问题讨论】:

【参考方案1】:

当我遇到这些情况时,我将extra 字段设为可空(将extra: UserExtra! 替换为extra: UserExtra)。有很多文章介绍了如何处理 Graphql 架构中的可空性(This 和 this 是对我有影响的两篇)。

据推测,extra 字段在不同的解析器中是分开的,因为您必须做一些额外的工作来获取它们,例如从另一个服务或数据存储请求数据。如果该请求最终失败,架构最好将类型声明为可为空,这样其余的用户数据仍会返回,并将 extra 设置为 null,而不是因为 extra 而丢弃其他 user 数据为 null 并违反架构类型。 this article 中的 Non-null fields mean small failures have an outsized impact 很好地详细解释了这个问题。折衷方案是,您的客户端代码需要检查 extra 是否为空,但有人可能会争辩说,这会迫使您的客户端代码考虑更优雅地处理看似合理的失败案例,这是一件好事。

此更改还将解决您尝试解决的原始问题,因为 extra 将是生成的 graphql-code-generator 类型中的可选类型,并且您的主要用户解析器不需要返回它。

【讨论】:

以上是关于使用 GraphQL 代码生成器从解析器返回不完整的形状的主要内容,如果未能解决你的问题,请参考以下文章

从 graphql yoga 返回状态码

无法将自定义结果从解析器传递到 Graphql

类型 Graphql 自定义解析器

GraphQL:从兄弟解析器访问另一个解析器/字段输出

使用来自突变解析器的 GraphQL Yoga 响应自定义 HTTP 代码

Nestjs / GraphQL - Playground 为查询返回 Null 错误。我的解析器?