1

我在 graphql 中编写 API 时遇到了一些困难。

我的 api 中的每个响应都应该看起来有些相同。所以理想情况下,这将是 graphql 类型:

type Response {
  success
  data {
    ... always different
  }
  errors {
    path
    message
  }
}

但是因为这里的数据字段总是不同的。每个突变/查询都应该有自己的响应类型(如果我正确理解了 graphql)。

所以对于登录,这是我使用转换器函数创建的类型:

type LoginResponse {
  success
  data {
    user
    token
  }
  errors {
    path
    message
  }
}

现在在我的前端,我想使用以下片段,因为这些属性始终存在于每个响应中。

fragment Response on LoginResponse {
  success
  errors {
    path
    message
  }
}

所以我遇到的问题已经在这里显示了,您还可以使用片段定义它的父类型。因此,我必须创建与单独响应类型一样多的单独片段。

是否有人可能已经为此苦苦挣扎,或者是否有最佳实践我没有看到

4

2 回答 2

2

通常,当您有一个可以解析为多种类型之一的字段时,您可以使用联合。如果这些类型共享一个或多个字段,您可能希望使用接口来代替。

您在模式中看到的一个常见模式是Node接口的概念。您可以通过 id 获取节点的查询,例如:

type Query {
  node(id: ID!): Node
}

interface Node {
  id: ID!
}

type Foo implements Node {
  id: ID!
  foo: String!
}

type Bar implements Node {
  id: ID!
  bar: Int!
}

在这里,aNode可以是Fooor 或 a Bar,所以如果我们要为 编写一个片段Node,它可能看起来像这样:

fragment NodeFields on Node {
  id # id is part of the interface itself
  ... on Bar {
    bar # fields specific to Bar
  }
  ... on Foo {
    foo # fields specific to Foo
  }
}

如果您没有共享字段,则可以使用 Union 代替以达到相同的效果:

union SomeUnion = Foo | Bar

因此,为了减轻前端代码中的一些重复,您可以将每个Result类型设为接口,或者更好的是,将单一Result类型data作为联合。不幸的是,接口或联合都不能与标量或列表一起使用,如果data某些查询应该是标量或列表,这会使事情变得复杂。

但是,归根结底,首先可能不建议您以这种方式构建架构。避免这种结构有很多很好的理由:

  1. GraphQL 已经将您的查询结果作为带有dataerrors属性的 JSON 对象返回。
  2. 在 GraphQL 中返回错误data将需要额外的逻辑来捕获和格式化错误,而不是能够在任何地方抛出错误并让 GraphQL 为您处理错误报告。
  3. 您将无法捕获验证错误,因此您最终可能会在两个地方遇到错误——在errors数组内部和内部data.errors。这也意味着您的客户需要在两个位置查找错误以进行正确的错误处理。
  4. GraphQL 专门设计用于允许部分解析响应。这意味着即使响应的某些部分出错并且无法解析,其他部分仍可能被解析并作为响应的一部分返回。这意味着响应“成功”的概念并不真正适用于 GraphQL。如果您绝对需要一个success字段,最好formatResponse在查询解析后使用类似将其添加到响应对象中的方法。

坚持约定会让事情变得更加简单,并按照以下思路构建架构:

type Query {
  login: LoginResponse
}

type LoginResponse {
  token: String
  user: User
}

实际响应仍将包括dataand errors

{
  "data": {
    "login": {
      "token": "",
    }
  },
  "errors": []
}

如果您甚至需要使用片段,您仍然需要每种类型一个片段,但片段之间的重复将大大减少。

于 2018-12-13T03:05:10.047 回答
0

如何处理错误的好视频(与此问题相关):https ://www.youtube.com/watch?v=-wRXk_QZ3Ko

于 2018-12-22T12:47:25.193 回答