angularfire: snapshotChanges trigger twice

Version info

Angular:8

AngularFire:"5.2.1

I have main component that retrieve data from collection and i have sub component that retrieve different data from the same collection.

whats happened is that the sub-component snapshotChanges() trigger twice with the data it should retrieve and the data that retrieved by the parent component.

Parent component:

this.firestore.collection('galleries', ref => ref.where('user', '==', this.user.id)
      .orderBy('date', 'desc'))
      .snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data() as any;
        data.id = a.payload.doc.id;
        return data;
      }))).subscribe((sessions) => {
         console.log(sessions);
      });

Child component:

this.firestore.collection('galleries', ref => ref.limit(6).orderBy('date', 'desc'))
      .snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data() as any;
        data.id = a.payload.doc.id;
        return data;
      }))).subscribe((sessions) => {console.log(sessions)})

in the child component i’ve limit the query to 6 document ’ but it’s subscription called twice, and displays both parent data child documents. Any idea?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 19 (1 by maintainers)

Most upvoted comments

This is my solution using RxJS operator distinctUntilChanged and lodash isEqual function. With it you can avoid twice triggering and get benefits from the cache usage

this.afs.collection(path).doc<any>(id).snapshotChanges()
  .pipe(distinctUntilChanged((prev, curr) => _.isEqual(prev?.payload.data(), curr?.payload.data())))

similar for valueChanges

this.afs.collection(path).doc<any>(id).valueChanges()
  .pipe(distinctUntilChanged((prev, curr) => _.isEqual(prev, curr)))

i have the same problem.

this occurs when i do a snapshotChanges() on a collection, while there is already another active snapshotChanges() on the same collection. the late coming subscription first receives the results cached from the former subscription. then after a while it receives the actual results.

i think this is a very problematic design. when i execute a query, it should return me only once, not twice. i shouldn’t be trying to handle two different results from one query. this either complicates my code, or makes me disable some features i would like to present to my users.

the cached results should be returned only when firestore servers can not be contacted, that is, the query should return either the correct result or cached result. not both.

I think it would be fine that it returns twice, if there were also a way for me to differentiate where the data came from. Then I could decide for myself when to display cached results.

My solution is kind of hacky but I include auditTime(2000) in the pipe to provide enough time for that second query to come through.

this.collection$(path, query).pipe(auditTime(2000),take(1)).toPromise();

Yes it’s like super basic and no one complains about it