在Apollo iOS中使用@defer指令
⚠️ 在Apollo iOS中的@defer
指令目前是一个实验性功能
,自1.14.0版本起可用。如果您对该功能有任何反馈,请通过新的GitHub问题告诉我们,或者通过任何现有的与@defer相关的现有问题进行搜索。
The @defer
指令 允许您的查询异步接收特定 字段 的数据。这在对一些字段的解析时间远长于其他字段时非常有用。
例如,假设我们正在构建一个社交媒体应用程序,它可以快速获取用户的基本资料信息,但获取该用户的朋友信息却需要更长的时间。如果我们希望在单个 查询 中包括所有这些 fields 字段,我们希望能够在基本资料信息可用时立即显示,而不是等待 friends
字段 解析完成。
要实现这一点,我们可以将 @defer
指令 应用到一个包含所有与朋友数据相关慢解析 fields 字段的内联 片段 上:
query PersonQuery($personId: ID!) {person(id: $personId) {# Basic fields (fast)idfirstNamelastName# Friend fields (slower)... on User @defer(label: "deferredFriends") {friends {id}}}}
在本查询生成的代码中,asUser
类型将可选项,它还将包含一个fragments
容器,该容器中将包含一个与在查询中使用的label
属性值相同的可选项片段。延迟的片段是可选项的,因为它不会被包含在基本字段中,而是在单独的响应中返回。
所有的延迟片段都已经用@Deferred
属性包装。这允许您通过投影值来检查任何延迟片段的状态。当延迟片段的字段被接收到时,将返回另一个包含所有基本字段和friends
字段的响应。
client.fetch(query: ExampleQuery()) { result inswitch (result) {case let .success(data):if case .fulfilled = data.data?.person.asUser?.fragments.$deferredFriends {print("Query Success! Received all fields.")} else {print("Query Success! Received basic fields only.")}case let .failure(error):print("Query Failure! \(error)")}}
将打印类似的内容
Query Success! Received basic fields only.Query Success! Received all fields.
要求
- 必须在类型选择中使用@defer指令。
- @defer指令必须有
label
属性。
缓存
读取缓存数据
对于使用@defer指令的操作,也支持典型的缓存行为和功能。与网络请求相比,缓存读取的行为略有不同,因为.所有缓存的数据,包括任何缓存的延迟片段,都将包含在第一个响应中。换句话说,如果整个查询已被缓存,则只有一个包含所有基本和延迟片段的响应。如果您手动将只有基本数据添加到缓存中,那么在第一个响应中您将只收到基本数据,并且根据使用的缓存策略,可能会从网络中单独返回延迟片段。
写入缓存数据
我们仍在构建对延迟片段的兼容性。选择集初始化器。直到那时,要将内容写入缓存,需要使用私有 .init(_dataDict: DataDict)
函数初始化本地缓存 mutation,或使用命名的片段 选择集。