在 Apollo Kotlin 中使用 @defer 指令
异步获取较慢的 schema 字段
在 Apollo Kotlin 中,@defer
指令目前是 实验性。如果你对此有任何反馈,请通过 GitHub issues或在 Kotlin Slack 社区反馈给我们。
Apollo Kotlin 提供了对 《code class="css-1lvdtfu">@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.dataOrThrow().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
代码生成一起使用。- 某些服务器可能会发送一个空负载以指示流的结束。在这种情况下,你会收到一个额外的终端发射。你可以通过使用
distinctUntilChangedBy()
过滤它:
apolloClient.query(MyQuery()).toFlow().distinctUntilChangedBy { it.data } // filter out duplicates.collect { /* ... */ }