AngularFire2中db.collection.add重复创建两条相同数据问题求助
解决Firestore重复添加条目问题
看起来你遇到的问题是每次上传文件时,Firestore的photos集合都会被添加两条完全相同的文档。这种情况通常有两个常见原因,我来帮你分析并给出修复方案:
可能的原因1:Observable被多次订阅
你的代码里用了this.task.snapshotChanges(),这是一个冷Observable——每次订阅它,都会重新触发整个上传事件流。如果你的组件里同时存在两种订阅方式(比如模板中用了async管道,同时在组件类里又手动调用了subscribe()),那么每一次订阅都会执行tap里的Firestore添加逻辑,导致重复创建文档。
可能的原因2:完成事件被多次触发
在某些Firebase Storage SDK版本或网络场景下,snapshotChanges()可能会在上传完成时多次发出相同的“完成状态”快照,导致你的条件snap.bytesTransferred === snap.totalBytes被触发两次。
修复方案
方案1:使用finalize操作符(推荐)
finalize操作符会在Observable完成时仅执行一次,不管中间有多少个事件触发,非常适合处理上传完成后的收尾逻辑。修改你的代码如下:
this.snapshot = this.task.snapshotChanges().pipe( tap(snap => console.log(snap)), finalize(() => { // 仅在上传完全结束后执行一次 this.db.collection('photos').add({ path, size: this.task.snapshot.totalBytes }); }) );
方案2:用filter + take(1)确保只处理一次完成事件
如果你还是想基于快照的字节传输判断完成状态,可以结合filter和take(1)来保证逻辑只执行一次:
this.snapshot = this.task.snapshotChanges().pipe( tap(snap => console.log(snap)), // 过滤出完成状态的快照 filter(snap => snap.bytesTransferred === snap.totalBytes), // 只取第一个符合条件的事件,之后自动取消订阅 take(1), tap(snap => { this.db.collection('photos').add({ path, size: snap.totalBytes }); }) );
额外检查:避免重复订阅
如果你的模板里有类似这样的代码:
<div *ngIf="snapshot | async">上传中...</div>
同时组件类里又手动订阅了snapshot,请移除其中一个订阅方式,或者把snapshot转为热Observable(比如用shareReplay())来避免重复执行逻辑。
内容的提问来源于stack exchange,提问作者Budi
相关产品推荐
相关产品推荐

