Attendez que Firebase ait fini de charger les données (vue) / 'await' ne fonctionne pas

Jan 11 2021

Dans mon application vue, je récupère des données de Firebase dans le created-hook. Je veux que le code soit exécuté après la fin du chargement des données. Mais je ne peux pas le faire fonctionner.

Voici mon code:

<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>

Mais une console, d'abord 'Done with fetching Data'est affichée, puis null(parce qu'elle this.settingsest toujours null) et seulement après que l'Objekt settingsest imprimé. Mais j'ai besoin this.settingsd'être défini là-bas (et plus nullmaintenant) pour travailler avec là-bas.

Ce que j'ai essayé jusqu'à présent:

  1. La mise en attend
  2. Ajout d'un chargé parameter
  3. Ajout du code par la suite dans un then()

Rien n'a fonctionné.

Réponses

3 RenaudTarnec Jan 11 2021 at 00:56

La onSnapshot()méthode n'est pas une méthode asynchrone. Comme expliqué dans le doc, il "attache un écouteur pour les DocumentSnapshotévénements".

Donc, vous devriez l'utiliser si vous voulez définir un écouteur continu pour le document Firestore: si quelque chose change dans le document (par exemple un champ obtient une nouvelle valeur), l'écouteur sera déclenché. Notez que "un appel initial utilisant le rappel que vous fournissez crée immédiatement un instantané de document avec le contenu actuel du document unique" (voir le document ).

Vous obtenez les données du document Firestore uniquement dans la fonction de rappel à laquelle vous passez onSnapshot(), comme suit:

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

Comme Nilesh Patel l'a mentionné, notez que vous devez utiliser une fonction de flèche pour pouvoir l'utiliser thisdans ce rappel . Notez également que la createdfonction n'a PAS besoin d'être asynchrone .

Enfin, notez qu'il est onSnapshot()recommandé d'appeler la fonction de désabonnement renvoyée par lorsque vous détruisez le composant Vue.js. Utilisez le beforeDestroycrochet comme suit:

// ...
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'autre part, si vous souhaitez simplement lire les données du document UNE SEULE FOIS dans le hook Vue.js créé, vous devez utiliser la get()méthode, comme suit:

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!");
    }
}

Notez que, dans ce cas, la createdfonction DOIT être async, car elle get()est asynchrone.


Plus de détails sur la différence entre get()et onSnapshot()dans cette réponse SO .

1 NileshPatel Jan 11 2021 at 00:46

essayez d'utiliser la fonction fléchée

  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)
  },