意外的 Firebase Firestore 集合订阅行为
Unexpected Firebase Firestore collection subscription behaviour
我在订阅集合的 valueChanges 时遇到了一些有趣的行为。
创建文档后,立即调用集合的订阅,但我收到的不是许多文档的数组,而是一个大小为 one 的数组 - 单个新创建的文档。
看完这篇(Firestore Docs | Get Realtime Updates)我还是有点迷糊。
Local writes in your app will invoke snapshot listeners immediately. This is because of an important feature called "latency compensation." When you perform a write, your listeners will be notified with the new data before the data is sent to the backend.
这是否解释了我所看到的行为?
这里 stackblitz 演示了这个问题。只需取消注释掉 ngOnInit() 中的注释行并重新加载以查看我认为是预期的行为。
我可以通过在其他地方使用空订阅收听此集合,或者直接在
之前复制 take(1) 订阅代码来解决这个问题
这是一个很好的收获。很确定你是对的 - valueChanges()
如文档所述:
The current state of your collection. Returns an Observable of data as
a synchronized array of JSON objects.
当你发现自己时:
Local writes in your app will invoke snapshot listeners immediately.
事情是这样的:
您的 addPizza()
是一个 async 函数。它向 backed 发送添加新比萨饼的请求。但它不会等待任何事情并跳转到您的第二个函数 - this.getPizzasAsyncAwait()
。因为本地写入会立即调用侦听器,所以您的 Observable 会发出该值并广播它。并且由于您还使用 Rxjs 的 take(1)
- 之后它取消订阅。这也解释了为什么 take(2)
带来所有其他记录。您可以将 getPizzasNormal()
方法移至 OnInit()
,您将收到整个集合。
firebase js sdk 乐观处理添加,在获取集合值之前,集合还没有定义。添加一个值后,该集合包含 1 个值,然后由服务器端值更新。
如果您希望避免在仅根据本地更改设置集合值时获得此中间状态,您可以在开始之前订阅要在订阅之前完成的更改:
this.piazzaRef.add({
name: name,
addedAt: new Date().toISOString()
}).then(() => {
this.getPizzasAsyncAwait();
this.getPizzasNormal();
});
我在订阅集合的 valueChanges 时遇到了一些有趣的行为。
创建文档后,立即调用集合的订阅,但我收到的不是许多文档的数组,而是一个大小为 one 的数组 - 单个新创建的文档。
看完这篇(Firestore Docs | Get Realtime Updates)我还是有点迷糊。
Local writes in your app will invoke snapshot listeners immediately. This is because of an important feature called "latency compensation." When you perform a write, your listeners will be notified with the new data before the data is sent to the backend.
这是否解释了我所看到的行为?
这里 stackblitz 演示了这个问题。只需取消注释掉 ngOnInit() 中的注释行并重新加载以查看我认为是预期的行为。
我可以通过在其他地方使用空订阅收听此集合,或者直接在
之前复制 take(1) 订阅代码来解决这个问题这是一个很好的收获。很确定你是对的 - valueChanges()
如文档所述:
The current state of your collection. Returns an Observable of data as a synchronized array of JSON objects.
当你发现自己时:
Local writes in your app will invoke snapshot listeners immediately.
事情是这样的:
您的 addPizza()
是一个 async 函数。它向 backed 发送添加新比萨饼的请求。但它不会等待任何事情并跳转到您的第二个函数 - this.getPizzasAsyncAwait()
。因为本地写入会立即调用侦听器,所以您的 Observable 会发出该值并广播它。并且由于您还使用 Rxjs 的 take(1)
- 之后它取消订阅。这也解释了为什么 take(2)
带来所有其他记录。您可以将 getPizzasNormal()
方法移至 OnInit()
,您将收到整个集合。
firebase js sdk 乐观处理添加,在获取集合值之前,集合还没有定义。添加一个值后,该集合包含 1 个值,然后由服务器端值更新。
如果您希望避免在仅根据本地更改设置集合值时获得此中间状态,您可以在开始之前订阅要在订阅之前完成的更改:
this.piazzaRef.add({
name: name,
addedAt: new Date().toISOString()
}).then(() => {
this.getPizzasAsyncAwait();
this.getPizzasNormal();
});