Aguarde até que o firebase termine de carregar os dados (vue) / 'await' não está funcionando

Jan 11 2021

Em meu aplicativo vue, estou buscando alguns dados do createdfirebase no -hook. Eu quero que o código seja executado depois que os dados forem carregados. Mas não consigo fazer funcionar.

Aqui está o meu código:

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

Mas um console, primeiro 'Done with fetching Data'é exibido, depois null(porque this.settingsainda está null) e só depois disso o Objekt settingsé impresso. Mas eu preciso this.settingsser definido lá (e não nullmais) para trabalhar lá.

O que tentei até agora:

  1. Colocando em espera
  2. Adicionando um carregado parameter
  3. Adicionando o código posteriormente em um then()

Nada funcionou.

Respostas

3 RenaudTarnec Jan 11 2021 at 00:56

O onSnapshot()método não é um método assíncrono. Conforme explicado no documento, ele "anexa um ouvinte para DocumentSnapshoteventos".

Portanto, você deve usá-lo se quiser definir um ouvinte contínuo para o documento Firestore: se algo mudar no documento (por exemplo, um campo recebe um novo valor), o ouvinte será acionado. Observe que "uma chamada inicial usando o retorno de chamada que você fornece cria um instantâneo do documento imediatamente com o conteúdo atual do único documento" (consulte o documento ).

Você obtém os dados do documento Firestore apenas na função de retorno de chamada que você passa para onSnapshot(), da seguinte maneira:

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

Como Nilesh Patel mencionou, observe que você precisa usar uma função de seta para usar thisneste retorno de chamada . Observe também que a createdfunção NÃO precisa ser assíncrona .

Por fim, observe que é uma boa prática chamar a função de cancelamento de assinatura retornada por onSnapshot()quando você destrói o componente Vue.js. Use o beforeDestroygancho da seguinte maneira:

// ...
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();
  }
},

Por outro lado, se você deseja apenas ler os dados do documento SOMENTE UMA VEZ no gancho Vue.js criado, você deve usar o get()método da seguinte maneira:

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

Observe que, neste caso, a createdfunção PRECISA ser async, pois get()é assíncrona.


Mais detalhes sobre a diferença entre get()e onSnapshot()nesta resposta SO .

1 NileshPatel Jan 11 2021 at 00:46

tente usar a função de seta

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