Firestore 离线缓存和承诺

Firestore Offline Cache & Promises

这个问题是 Firestore offline cache. I've read the offline cache documentation 的后续问题,但有一点我很困惑。

一位评论者回答了上一个问题(~ ​​一年前):

You Android code that interact with the database will be the same whether you're connected or not, since the SDK simply works the same."

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

Returns non-null Promise containing void A promise that resolves once the data has been successfully written to the backend. (Note that it won't resolve while you're offline).

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

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

A Promise that resolves with a DocumentReference pointing to the newly created document after it has been written to the backend.

这有点模糊,因为不确定 "backend" 在这种情况下是否是 "cache" 和 "server" 的超集,或者它是否仅表示服务器。如果这个没有解决,那就意味着下面的方法不起作用,对吗?

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

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

你这里有两个问题,其实并没有什么关系。我会分别解释它们。

在大多数情况下,开发人员通常不关心来自文档更新的承诺是否实际解决。几乎总是 "fire and forget"。只要应用程序无论如何都以相同的方式运行,那么如果应用程序知道更新已到达服务器,它会获得什么好处?本地缓存已更新,以后所有查询都会显示文档已更新,即使更新尚未与服务器同步。

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


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

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