意外的Firebase Firestore集合订阅行为

时间:2018-04-03 12:25:36

标签: javascript angular rxjs rxjs5

我正在体验关于集合的valueChanges订阅的一些有趣行为。

创建文档后,立即调用集合的订阅,但而不是许多文档的数组我只收到一个大小为1的数组 - 单个新创建的文档。

在仔细阅读(Firestore Docs | Get Realtime Updates)之后,我仍然感到有些困惑。

  

您应用中的本地写入将立即调用快照侦听器。这是因为一项称为“延迟补偿”的重要功能。"当您执行写操作时,在将数据发送到后端之前,将通过新数据通知您的侦听器。

这是否解释了我所看到的行为?

这是展示问题的stackblitz。只需取消注释ngOnInit()中的注释行并重新加载即可查看我认为的预期行为。

我可以通过在其他地方监听此集合的空订阅或在之前直接复制take(1)订阅代码来解决此问题

2 个答案:

答案 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();
});

I updated your example here