我在用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
}
}
因此,我遇到的问题已经在此处显示,您还可以通过片段定义其父类型。因此,我必须创建与单独的响应类型一样多的单独的片段。
有人可能已经为此感到挣扎了吗?还是我没有看到针对这种情况的最佳实践?
答案 0 :(得分:1)
通常,当您拥有可以解析为多种类型之一的字段时,可以使用联合。如果这些类型共享一个或多个字段,则可能要使用一个Interface。
在模式中看到的常见模式是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!
}
在这里,Node
可以是Foo
或Bar
,所以如果我们要为Node
编写一个片段,它可能看起来像这样:< / p>
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 SomeUnion = Foo | Bar
因此,为减轻前端代码中的某些重复,您可以使每个Result
类型成为一个接口,或者更好的是,将单个Result
类型与{{1 }}成为工会。不幸的是,接口或联合都不能与标量或列表一起使用,如果data
被认为是某些查询的标量或列表,则会使情况变得复杂。
但是,到最后,不建议您首先以这种方式构造架构。有许多避免这种结构的充分理由:
data
和data
属性的JSON对象返回查询结果。errors
内部返回错误将需要附加的逻辑来捕获和格式化错误,而不是能够在任何地方抛出错误并让GraphQL为您处理错误报告。data
数组内部和errors
内部。这也意味着您的客户需要在两个位置查找错误以进行正确的错误处理。data.errors
字段,那么在查询解析后,最好使用success
之类的东西将其添加到响应对象中。遵循约定将使事情变得更加简单,并按照以下方式构建架构:
formatResponse
实际响应仍将包括type Query {
login: LoginResponse
}
type LoginResponse {
token: String
user: User
}
和data
:
errors
即使您甚至需要使用片段,每种类型仍然需要一个片段,但是片段之间的重复将大大减少。
答案 1 :(得分:0)
有关如何处理错误(与此问题相关)的优质视频:https://www.youtube.com/watch?v=-wRXk_QZ3Ko