在 Apollo Kotlin 中使用 @defer 指令
异步获取较慢的架构字段
⚠️ 在 Apollo Kotlin 中的 @defer
指令已被默认启用。如果您有关于它的反馈,请通过 GitHub 问题反馈 或在 Kotlin Slack 社区 中联系我们。.
从版本 3.6.0
开始, Apollo Kotlin提供了对 @defer
指令的支持,这允许您的查询异步地接收特定 字段的数据。当一个 查询 中的一些字段比其他字段处理时间更长时,这非常有用。
例如,假设我们正在开发一个社交媒体应用程序,该程序可以快速检索用户的个人资料信息,但获取该用户的朋友信息则耗时较长。如果我们在一个查询中包括所有这些字段,我们希望能够在信息可用时立即显示个人资料信息,而不是等待朋友字段解析完毕。
为了实现这一点,我们可以将@defer
指令应用于包含所有与朋友数据相关的慢解析字段的内部片段。
query PersonQuery($personId: ID!) {person(id: $personId) {# Basic fields (fast)idfirstNamelastName# Friend fields (slower)... on User @defer {friends {id}}}}
在此查询生成的代码中,片段的onUser
字段将为可空字段。这是因为当从服务器接收初始有效负载时,片段的字段尚未存在。Person
将只填充基本字段的实例。
当片段的字段可用时,将发出一个新的Person
实例,这次将为onUser
字段提供数据,并填充片段中的字段。
apolloClient.query(PersonQuery(personId)).toFlow().collect {println("Received: $it")if (it.dataAssertNoErrors.person.onUser == null) {// Initial payload: basic info only// ...} else {// Subsequent payload: with friends// ...}}
将打印类似以下内容
Received: Person(id=1, firstName=John, lastName=Doe, onUser=null))Received: Person(id=1, firstName=John, lastName=Doe, onUser=OnUser(friends=[Friend(id=2), Friend(id=3)]))
局限性/已知问题
@defer
无法与responseBased
代码生成一起使用。- 某些服务器可能会发送一个空的有效载荷来表示流的结束。在这种情况下,您将收到额外的终端发射。您可以通过使用
distinct()
来过滤它:
apolloClient.query(MyQuery()).toFlow().distinct() // filter out duplicates.collect { /* ... */ }