Wait until firebase has finished loading data (vue) / 'await' not working
Answer a question
In my vue app, I am fetching some data from firebase in the created
-hook. I want the code afterwards to be exectuted after the data was finished with loading. But I can not make it work.
Here is my 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>
But one the console, first 'Done with fetching Data'
is displayed, then null
(because this.settings
is still null
) and only after that the Objekt settings
is printed. But I need this.settings
to be defined there (and not null
anymore) to work with there.
What I tried so far:
- Putting in awaits
- Adding a loaded
parameter
- Adding the code afterwards in a
then()
Nothing worked.
Answers
The onSnapshot()
method is not an asynchronous method. As explained in the doc, it "attaches a listener for DocumentSnapshot
events".
So, you should use it if you want to set a continuous listener to the Firestore document: if something changes in the document (e.g. a field gets a new value) the listener will be triggered. Note that "an initial call using the callback you provide creates a document snapshot immediately with the current contents of the single document" (see the doc).
You get the Firestore document data only in the callback function that you pass to onSnapshot()
, as follows:
created() {
institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(doc => {
this.settings = doc.data();
console.log(this.settings);
});
}
As Nilesh Patel mentioned, note that you need to use an arrow function in order to use this
in this callback. Also note that the created
function does NOT need to be async.
Finally, note that it is a good practice to call the unsubscribe function returned by onSnapshot()
when you destroy the Vue.js component. Use the beforeDestroy
hook as follows:
// ...
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();
}
},
On the other hand, if you just want to read the document data ONLY ONCE in the created Vue.js hook, you should use the get()
method, as follows:
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!");
}
}
Note that, in this case, the created
function NEEDS to be async
, since get()
is asynchronous.
More details on the difference between get()
and onSnapshot()
in this SO answer.
更多推荐
所有评论(0)