延迟查询响应数据
使用 @defer 指令
在 GraphOS 中,您的 supergraph 的 路由器 可以延迟返回 schema 中的某些 fields 的数据。这使查询客户端能够更快速地接收非延迟数据,因为路由器可以立即返回它,而无需等待所有响应数据准备就绪:
都支持云超图 和 自托管超图 都支持路由器延迟返回 fields。另外,此功能与所有 支持的 subgraph 库 兼容,因为逻辑完全位于 router 内部!
如何在查询中延迟.fields 呢?
ⓘ 注意
延迟 查询 字段需要使用一个与延迟兼容的客户端库。这些库支持通过分块HTTP响应逐步接收查询数据。
当前,延迟支持在 Apollo 客户端 中提供,适用于 Web 和 Kotlin (实验性)。
如果你正在使用与延迟兼容的客户端,则可以对@defer
指令应用于 片段来指定要延迟哪些 字段。
query GetTopProductsAndReviews {topProducts {idname# You always apply @defer to a fragment, not to individual fields... @defer {reviews {score}}}}
当你的 supergraph's 路由器 接收到此 查询 时,它会延迟这些 片段 中的每个 字段。
我的路由器可以延迟哪些字段?
您的 supergraph's 路由器可以在您的模式中延迟以下 字段:
- 类型 Query 的根 字段(及其子字段)
- 字段 任何 实体 类型(及其子字段)
- 延迟实体字段功能非常强大,但如果您尚未使用实体,则需要一些配置。有关详细信息,请参阅以下内容。
下面提供了有关这些内容的更多信息。
Query
字段
您的路由器可以延迟您模式中的Query
类型的任何字段,以及这些字段的任何子字段:
query GetUsersAndDeferProducts {users {id}... @defer {products {id}}}
使用上述查询,路由器首先返回一个User
ID列表,然后稍后完成响应,返回Product
ID列表。
实体字段
您的路由器支持延迟超级图中的特殊对象类型的字段,这些对象类型称为实体。
实体是对象类型,它们通常在多个子图中定义它们的字段(但它们不必这样做)。您可以通过其@key
指令来识别一个entity
。在下面的示例子图模式中,Product
类型是一个entity:
type Product @key(fields: "id") {id: ID!name: String!price: Int!}type Query {topProducts: [Product!]!}
type Product @key(fields: "id") {id: ID!reviews: [Review!]!}type Review {score: Int!}
实体是子图的查询入口点,这也是路由器能够延迟它们的字段的原因:路由器可以给子图发送后续查询来获取任何初始未获取的实体字段。
以下是一个示例查询,使用上述子图延迟实体字段:
query GetProductsAndDeferReviews {topProducts {idname... @defer {reviews {score}}}}
为了处理此查询,路由器首先解析并返回包含其ID和名称的Product
对象列表。稍后,路由器通过返回每个产品的评论分数来完成响应。
ⓘ 注意
不会因为哪个子图定义了特定的实体字段而有所不同!查询可以延迟定义在任何数量不同的子图中的实体字段。
在您的子图中定义实体
如果您的子图还没有包括任何实体,则必须在客户开始查询中延迟它们的字段之前定义一些。
有关创建实体的相关信息,请参阅以下文章。
使用@defer
的要求
要成功使用@defer
,您的超级图及其客户端必须满足以下要求。这些要求分为一般要求(使用@defer
的一般要求)和实体特定要求(使用实体字段时对@defer
的附加要求)。
一般要求
- 客户端必须支持接收延迟查询响应作为多部分HTTP响应。
- 此功能目前支持在 Apollo Client 中使用,适用于 Web 以及 Kotlin (实验性)。
- 您的supergraph必须是以下之一:
- 一种 云超级图
- 一个 自托管超级图,运行 GraphOS Router
特定实体的要求
- 您每个子图 必须使用一个 子图兼容的GraphQL服务器库。
- 您必须在 子图模式中定义一个或多个实体。
- 每个子图 必须为其每个实体定义一个 引用解析器(或在您选择的子图库中实现相应功能)。
- 这正是使 路由器 能够直接访问实体字段并带有后续子查询的能力。