设计响应类型
查询和更新响应类型的最佳实践
更新的响应类型
💡 提示
另请参阅 结构化更新响应。
这种响应类型模式对于更新是有用的,因为它们可能导致许多有效的失败状态(例如尝试删除不存在的对象)。
例如,假设我们有一个电子商务 图。在执行 结账
更新时,如果购买的商品缺货或买家资金不足,该更新可能会失败。
如果我们定义一组 ErrorResponse
类型,前端开发者可以根据出现的失败类型提供定制化体验:
interface MutationResponse {status: ResponseStatus!}type CheckoutSuccess implements MutationResponse {status: ResponseStatus!cart: [Product!]!invoice: Invoice!}interface ErrorResponse {status: ResponseStatus!message: String!}type CheckoutError implements ErrorResponse {status: ResponseStatus!message: String!}union CheckoutResponse = CheckoutSuccess | CheckoutErrortype Mutation {checkout(cart: ID!): CheckoutResponse!}
查询的响应类型
假设我们有一个基本的 GraphQL API,它定义了以下 Query
类型:
type Query {users: [User!]!}
此 Query.users
字段 很直观:如果你 查询 它,你会得到一个 User
对象的列表。然而,这个返回类型并没有提供任何有关结果的信息:
- 如果列表为空,这是因为在用户数为零,还是发生了错误?
- 即使列表有数据,API 是否返回了所有用户,还是只是子集?
- 是否有多页结果?
为了回答这些类似的问题,对于查询层的 字段 返回 "包装" 对象可能很有帮助,这些对象可以包含操作结果以及执行操作的元数据。例如,在你需要 分页结果 或实现 Relay-style 连接 的模式时,这种模式可能会有所帮助。
示例:UsersResponse
以下示例为我们的 Query.users
字段定义了 UsersResponse
类型:
type User {id: ID!firstName: String!lastName: String!}type UsersResponse {offset: Int!limit: Int!totalResults: Int!data: [User!]!}type Query {users(limit: Int = 10, offset: Int = 0): UsersResponse!}
通过此更改,客户端的查询可以指定每页有多少结果,从哪一页开始,并了解可以进行分页的总结果数:
query FetchUsers {users(limit: 20, offset: 0) {totalResultsdata {idfirstNamelastName}}}