Attendi fino a quando Firebase ha terminato il caricamento dei dati (vue) / "Attendere" non funziona

Jan 11 2021

Nella mia app vue, sto recuperando alcuni dati da Firebase nel created-hook. Voglio che il codice venga eseguito successivamente al termine del caricamento dei dati. Ma non riesco a farlo funzionare.

Ecco il mio codice:

<template>
    <div>
        <h1>Test 2</h1>
    </div>
</template>

<script>
import { institutesCollection } from '../firebase';
export default {
    name: 'Test2',
    data() {
        return {
            settings: null,
        }
    },
    async created() {
        await institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(
            await function(doc) {
                this.settings = doc.data();
                console.log(this.settings);
            }
        )
        console.log('Done with fetching Data');
        console.log(this.settings)
    },
    methods: {
        
    }
}
</script>

Ma prima 'Done with fetching Data'viene visualizzata la console, poi null(perché this.settingsè ferma null) e solo dopo settingsviene stampato l'Oggetto . Ma ho bisogno this.settingsdi essere definito lì (e non nullpiù) per lavorarci.

Quello che ho provato finora:

  1. Mettere in attesa
  2. Aggiunta di un file parameter
  3. Aggiungendo il codice in seguito in un file then()

Niente ha funzionato.

Risposte

3 RenaudTarnec Jan 11 2021 at 00:56

Il onSnapshot()metodo non è un metodo asincrono. Come spiegato nel documento, "allega un listener per gli DocumentSnapshoteventi".

Quindi, dovresti usarlo se vuoi impostare un ascoltatore continuo al documento Firestore: se qualcosa cambia nel documento (ad esempio un campo riceve un nuovo valore) il listener verrà attivato. Notare che "una chiamata iniziale utilizzando il callback fornito crea immediatamente un'istantanea del documento con il contenuto corrente del singolo documento" (vedere il documento ).

Ottieni i dati del documento Firestore solo nella funzione di callback a cui passi onSnapshot(), come segue:

created() {
    institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(doc => {
           this.settings = doc.data();
           console.log(this.settings);
      });
}

Come accennato da Nilesh Patel, tieni presente che devi utilizzare una funzione freccia per thispoterla utilizzare in questo callback . Si noti inoltre che la createdfunzione NON deve essere asincrona .

Infine, onSnapshot()tieni presente che è una buona pratica chiamare la funzione di annullamento dell'iscrizione restituita da quando distruggi il componente Vue.js. Usa il beforeDestroygancio come segue:

// ...
data() {
    return {
        settings: null,
        firestoreListener: null
    }
},
created() {
    this.firestoreListener  = institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(doc => {
           this.settings = doc.data();
           console.log(this.settings);
      });
},
beforeDestroy() {
  if (this.firestoreListener) {
    this.firestoreListener();
  }
},

D'altra parte, se si desidera leggere i dati del documento SOLO UNA VOLTA nell'hook Vue.js creato, è necessario utilizzare il get()metodo, come segue:

async created() {
    const doc = await institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').get();
    if (doc.exists) {
             this.settings = doc.data();
    } else {
             // doc.data() will be undefined in this case
             console.log("No such document!");
    }
}

Notare che, in questo caso, la createdfunzione DEVE essere async, poiché get()è asincrona.


Maggiori dettagli sulla differenza tra get()e onSnapshot()in questa risposta SO .

1 NileshPatel Jan 11 2021 at 00:46

prova a usare la funzione freccia

  async created() {
        await institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(
            doc => {
                this.settings = doc.data();
                console.log(this.settings);
            }
        )
        console.log('Done with fetching Data');
        console.log(this.settings)
  },