我正在体验关于集合的valueChanges订阅的一些有趣行为。
创建文档后,立即调用集合的订阅,但而不是许多文档的数组我只收到一个大小为1的数组 - 单个新创建的文档。
在仔细阅读(Firestore Docs | Get Realtime Updates)之后,我仍然感到有些困惑。
您应用中的本地写入将立即调用快照侦听器。这是因为一项称为“延迟补偿”的重要功能。"当您执行写操作时,在将数据发送到后端之前,将通过新数据通知您的侦听器。
这是否解释了我所看到的行为?
这是展示问题的stackblitz。只需取消注释ngOnInit()中的注释行并重新加载即可查看我认为的预期行为。
我可以通过在其他地方监听此集合的空订阅或在之前直接复制take(1)订阅代码来解决此问题
答案 0 :(得分:1)
这很好听。很确定你是对的 - valueChanges()
正如文档所述:
您收藏的当前状态。返回一个Observable of data as 一个JSON对象的同步数组。
当你发现自己时:
您应用中的本地写入将立即调用快照侦听器。
所以这就是:
您的addPizza()
是异步功能。它发送请求以支持添加新的比萨饼。但它不会等待任何事情并跳转到你的第二个函数 - this.getPizzasAsyncAwait()
。并且因为本地写入立即调用侦听器,所以Observable会发出该值并广播它。因为你也使用Rxjs的take(1)
- 之后它取消订阅。这也解释了为什么take(2)
带来了所有其他记录。您可以将getPizzasNormal()
方法移至OnInit()
,然后您将收到整个收藏集。
答案 1 :(得分:1)
firebase js sdk乐观地处理add,在获取集合值之前,尚未定义集合。添加值后,集合包含1个值,然后由服务器端值更新。
如果您希望在仅从本地更改设置集合值时避免获得此中间状态,则可以在订阅前开始更改之前进行订阅:
this.piazzaRef.add({
name: name,
addedAt: new Date().toISOString()
}).then(() => {
this.getPizzasAsyncAwait();
this.getPizzasNormal();
});