【问题标题】:Firestore Offline Cache & PromisesFirestore 离线缓存和承诺
【发布时间】:2018-09-13 03:35:12
【问题描述】:

这个问题是Firestore offline cache 的后续问题。我已经阅读了离线缓存documentation,但有一点很困惑。

一位评论者在上一个问题中回答了(〜一年前):

与数据库交互的 Android 代码将是相同的 无论您是否已连接,因为 SDK 的工作原理都是一样的。”

API documentation for DocumentReference's set method,我刚刚注意到它说:

退货 non-null Promise containing void 一次解决的承诺 数据已成功写入后端。 (请注意,它 离线时无法解决)。

强调我的。文档中的这一点不会表明代码的行为不同,还是我遗漏了什么?如果我在允许某些用户交互之前等待 .set() 解决,这听起来像是我需要为离线案例调整代码,而不是通常。

CollectionReference's add method 让我更加担心。它没有完全相同的注释,但说(强调我的):

一个 Promise,它通过 DocumentReference 解析,指向新创建的文档在写入后端后

这有点模糊,因为不确定在这种情况下“后端”是否是“缓存”和“服务器”的超集,或者它是否仅表示服务器。如果这个不能解决,那就意味着下面的行不通,对吗?

return new Promise((resolve, reject) => {
  let ref = firestore.collection(path)
  ref.add(data)
  .then(doc => {
    resolve({ id: doc.id, data: data })
  })
  ...
})

意思是,.add() 不会解析,.then() 不会运行,我也无法访问刚刚添加的文档的id。我希望我只是误解了一些东西,并且我的代码可以继续在线和离线运行。

【问题讨论】:

  • 您将此问题标记为“android”,但由于原生 Android 开发不涉及 Promise,因此我将其更改为“javascript”。原生 android 涉及到 Task 对象,它们相似,但不一样。
  • @DougStevenson - 好点。感谢您解决此问题。

标签: javascript google-cloud-firestore offline


【解决方案1】:

您在这里有两个问题,它们并不真正相关。我将分别解释它们。

在大多数情况下,开发人员通常不关心文档更新的承诺是否真正解决。它几乎总是“一劳永逸”。只要应用程序的行为方式相同,应用程序知道更新到达服务器会获得什么?本地缓存已更新,以后的所有查询都会显示文档已更新,即使更新尚未与服务器同步。

主要的例外是交易。 Transactions 要求服务器在线,因为需要在客户端和服务器之间进行往返以确保更新是原子的。交易根本无法离线工作。如果您需要知道交易是否有效,您需要在线。与正常的文档写入不同,事务不会保留在本地缓存中。如果应用在服务器上的事务完成之前被杀死,事务就会丢失。


您的第二个问题是新添加的文档,其中文档的 ID 在更新时未定义。 add() 确实返回了一个仅在服务器上存在新文档时才解析的承诺。在 Promise 为您提供新文档的 DocumentReference 之前,您无法知道文档的 ID。

如果此行为对您不起作用,您可以通过不带参数调用 doc() 而不是 add() 来为文档生成新 ID。 doc() 立即返回尚未写入的新(未来)文档的 DocumentReference(直到您选择编写它)。在doc()add() 的情况下,这些DocumentReference 对象包含在客户端生成的唯一ID。不同之处在于,使用doc(),您可以立即使用 id,因为您会立即获得 DocumentReference。使用add(),您不能这样做,因为在承诺解决之前不会提供 DocumentReference。如果您现在需要新的文档 ID,即使在离线时,也可以使用 doc() 而不是 add()。然后,您可以使用返回的 DocumentReference 离线创建文档,存储在本地缓存中,并稍后同步。然后更新将返回一个承诺,该承诺会在实际写入文档时解决。

【讨论】:

  • 非常有帮助,谢谢! 1)听起来我需要重新安排我的想法,以适应与过去不同的离线模式。在我的 UI 中,添加文档后(在“添加模式”屏幕中),它切换到同一文档的“查看模式”。在我目前的想法中,它在确认成功之前不会切换到新模式。我将努力转换到即发即弃的思维方式。问:如果写入缓存出现问题,.catch 还会触发吗? 2) 我错过了 doc() 与 add() 的区别。这绝对解决了我的问题,并为我提供了可以离线使用的前进道路。
  • 我不知道如果缓存写入失败,错误处理是什么样的。这将是非常罕见的(可能是磁盘空间不足?)。但我希望承诺会被拒绝。顺便说一句,有时向用户指示他们的更新与服务器完全同步是有用的。例如,对于聊天室,用户可能想知道其他人是否还可以看到他们的消息。您可以触发并忘记该消息,但这是对用户的礼貌,让他们知道发生了什么。无论如何,您都不想阻止他们尝试发送更多消息。
猜你喜欢
  • 1970-01-01
  • 2018-03-28
  • 2020-08-03
  • 2018-07-26
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
相关资源
最近更新 更多