2020 年 12 月 8 日 由 Rob Richard, Liliana Matos
Rob Richard 和 Liliana Matos 是 1stDibs.com 的前端工程师。他们一直与 GraphQL 工作组合作,作为
@defer和@stream指令的倡导者。
@defer 和 @stream 指令一直是备受期待的功能,自从 Lee Byron 在 2016 年 GraphQL 欧洲大会 上首次谈论它以来。在 2020 年的大部分时间里,我们一直在与 GraphQL 工作组合作,以标准化此功能。它现在是一个第二阶段提案,但为了进一步推进,我们希望 GraphQL 社区尝试使用这些指令并提供反馈。我们已经发布了 GraphQL.js 和 express-graphql 的实验版本。它们发布到 npm 中,名为 graphql@experimental-stream-defer 和 express-graphql@experimental-stream-defer。我们鼓励所有对该功能感兴趣的人尝试这些版本,并在 为反馈创建的问题 中告诉我们结果。继续阅读以了解有关此提案的更多信息。
GraphQL 的请求/响应模型的缺点之一是,GraphQL 响应只有在整个请求处理完成后才会返回给客户端。但是,并非所有请求的数据都具有同等重要性,在某些用例中,应用程序可能能够对请求数据的一部分进行操作。如果 GraphQL 服务器能够在数据准备就绪后立即发送最重要的数据,应用程序可以加快其交互时间。新的 @defer 和 @stream 指令允许 GraphQL 服务器通过从单个 GraphQL 响应返回多个有效负载来做到这一点。
@defer 指令可以应用于片段扩展和内联片段。它是一种声明式方法,允许开发人员将查询的某些部分标记为非必需立即返回。
以下是一个 @defer 指令的示例
query {  person(id: "cGVvcGxlOjE=") {    name    ...HomeworldFragment @defer(label: "homeworldDefer")  }}
fragment HomeworldFragment on Person {  homeworld {    name  }}
有效负载 1
{  "data": {    "person": {      "name": "Luke Skywalker"    }  },  "hasNext": true}
有效负载 2
{  "label": "homeworldDefer",  "path": ["person"],  "data": {    "homeworld": {      "name": "Tatooine"    }  },  "hasNext": false}
当 GraphQL 执行引擎遇到 @defer 指令时,它将分叉执行并开始异步解析这些字段。在延迟的有效负载仍在准备过程中,客户端可以接收并处理初始有效负载。当延迟数据量很大、加载成本很高或不在交互的关键路径上时,这非常有用。
与 @defer 类似,@stream 指令也允许客户端在整个结果准备就绪之前接收数据。@stream 可用于列表字段。以下是 @stream 指令的示例
query {  person(id: "cGVvcGxlOjE=") {    name    films @stream(initialCount: 2, label: "filmsStream") {      title    }}
有效负载 1
{  "data": {    "person": {      "name": "Luke Skywalker",      "films": [        { "title": "A New Hope" },        { "title": "The Empire Strikes Back" }      ]    }  },  "hasNext": true}
有效负载 2
{  "label": "filmsStream",  "path": ["person", "films", 2],  "data": {    "title": "Return of the Jedi"  },  "hasNext": true}
有效负载 3
{  "label": "filmsStream",  "path": ["person", "films", 3],  "data": {    "title": "Revenge of the Sith"  },  "hasNext": false}
当 GraphQL 执行引擎遇到 @stream 指令时,它将解析由 initialCount 参数指定的尽可能多的列表项。其余部分将异步解析。这对于仅在折线以上渲染少量元素的界面特别有用。客户端可以尽快渲染这些元素,而服务器仍在解析其余数据。
虽然 GraphQL 规范没有指定传输协议,但我们预计使用 @defer/@stream 的查询最常见的传输协议是带有分块传输编码的 HTTP。这允许 GraphQL 服务器保持标准的 HTTP 连接打开,同时在每个有效负载准备就绪后立即将其流式传输到客户端。它开销低,几十年来一直受到浏览器的支持,并且可以轻松地与大多数基础设施一起使用。
您可以在以下位置了解更多关于这些指令的信息:
– Rob Richard, Liliana Matos, 前端工程,1stDibs.com