Search code examples
javascriptangularfirebaseangularfire2angularfire2-offline

AngularFire returns results from cache AND server when enablePersistance is enabled


I use AngularFire (6.1.4) in my Angular (11.1.1) project with offline persistence and I was surprised to see that on load, the data is provided twice: once from the cache and once from the server (I use the variable fromCache to proof the source).

app.module.ts

import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';

@NgModule({
  imports: [
    AngularFireModule.initializeApp(Config),
    AngularFirestoreModule.enablePersistence(),
    AngularFireAuthModule
  ]
})
export class AppModule { ...}

DB Service

this.firestoreRef.collection(collectionName, query)
    .snapshotChanges()
    .pipe(
      map(actions => actions.map(a => {
         console.log('fromCache -> ', a.payload.doc.metadata.fromCache);
       }))
    ).subscribe(/* Just for TEST purposes */);

I was thinking the same logic for the get() options would apply:

Setting to default (or not setting at all), causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back to returning cached data if the server can't be reached.

Why also the cached data is returned if the user is online?

Of course I can listen offline/online events (though they are not reliable) or even a SW to check if the client is online or not, and use or skip the cached results accordingly, but shouldn't Firestore detect online/offline state?


Solution

  • From the documentation on listening to realtime updates:

    You can listen to a document with the onSnapshot() method. An initial call using the callback you provide creates a document snapshot immediately with the current contents of the single document.

    While this talks about a single document, the same applies when listening to multiple documents.

    So what you're seeing is just how Firestore works: when you attach a listener for the snapshot, it immediately fires with the local state of the data (if any). Then it checks against the server, which may take some time, and fires again with the state from the server, if that is different from the local cache (or you've requested to get called with metadata changes too).