Espere hasta que firebase haya terminado de cargar datos (vue) / 'await' no funciona
En mi aplicación vue, estoy obteniendo algunos datos de firebase en el created
-hook. Quiero que el código se ejecute después de que los datos hayan terminado de cargarse. Pero no puedo hacer que funcione.
Aquí está mi 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>
Pero primero 'Done with fetching Data'
se muestra la consola, luego null
(porque this.settings
está quieta null
) y solo después settings
se imprime el Objekt . Pero necesito this.settings
estar definido allí (y no null
más) para trabajar allí.
Lo que probé hasta ahora:
- Poner en espera
- Agregar un cargado
parameter
- Añadiendo el código posteriormente en un
then()
Nada funcionó.
Respuestas
El onSnapshot()método no es un método asincrónico. Como se explica en el documento, "adjunta un oyente para DocumentSnapshot
eventos".
Por lo tanto, debe usarlo si desea establecer un oyente continuo para el documento de Firestore: si algo cambia en el documento (por ejemplo, un campo obtiene un nuevo valor), el oyente se activará. Tenga en cuenta que "una llamada inicial con la devolución de llamada que proporciona crea una instantánea del documento inmediatamente con el contenido actual del documento único" (consulte el documento ).
Obtiene los datos del documento de Firestore solo en la función de devolución de llamada a la que pasa onSnapshot()
, de la siguiente manera:
created() {
institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(doc => {
this.settings = doc.data();
console.log(this.settings);
});
}
Como mencionó Nilesh Patel, tenga en cuenta que debe usar una función de flecha para usar thisen esta devolución de llamada . También tenga en cuenta que la created
función NO necesita ser asíncrona .
Finalmente, tenga en cuenta que es una buena práctica llamar a la función de cancelación de suscripción devuelta por onSnapshot()
cuando destruye el componente Vue.js. Utilice el beforeDestroy
gancho de la siguiente manera:
// ...
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 otro lado, si solo desea leer los datos del documento SOLO UNA VEZ en el enlace Vue.js creado, debe usar el get()método, de la siguiente manera:
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!");
}
}
Tenga en cuenta que, en este caso, la created
función NECESITA ser async
, ya que get()
es asíncrona.
Más detalles sobre la diferencia entre get()
y onSnapshot()
en esta respuesta SO .
intente usar la función de flecha
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)
},