Подождите, пока firebase завершит загрузку данных (vue) / 'await' не работает
В моем приложении vue я получаю некоторые данные из firebase в created
-hook. Я хочу, чтобы код выполнялся после того, как данные были загружены. Но я не могу заставить его работать.
Вот мой код:
<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>
Но сначала 'Done with fetching Data'
отображается консоль, затем null
(потому что this.settings
по-прежнему null
) и только после этого settings
печатается объект . Но мне нужно this.settings
быть там определенным (а не null
больше), чтобы работать с ним.
Что я пробовал до сих пор:
- В ожидании
- Добавление загруженного
parameter
- Добавление кода впоследствии в
then()
Ничего не получилось.
Ответы
Этот onSnapshot()метод не является асинхронным. Как объясняется в документе, он «присоединяет слушателя к DocumentSnapshot
событиям».
Таким образом, вы должны использовать его, если хотите установить непрерывный прослушиватель для документа Firestore: если что-то изменится в документе (например, поле получит новое значение), прослушиватель будет запущен. Обратите внимание , что «первоначальный вызов , используя функцию обратного вызова , которую Вы предоставили создает документ снимок сразу с текущим содержимым отдельного документа» (см документ ).
Вы получаете данные документа Firestore только в функции обратного вызова, которую вы передаете onSnapshot()
, как показано ниже:
created() {
institutesCollection.doc('FbdYJ5FzQ0QVcQEk1KOU').onSnapshot(doc => {
this.settings = doc.data();
console.log(this.settings);
});
}
Как упомянул Нилеш Патель, обратите внимание, что вам нужно использовать стрелочную функцию для использования thisв этом обратном вызове . Также обратите внимание, что created
функция НЕ должна быть асинхронной .
Наконец, обратите внимание, что рекомендуется вызывать функцию onSnapshot()
отмены подписки, возвращаемую при уничтожении компонента Vue.js. Используйте beforeDestroy
крючок следующим образом:
// ...
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();
}
},
С другой стороны, если вы просто хотите прочитать данные документа ТОЛЬКО ОДИН РАЗ в созданном хуке Vue.js, вы должны использовать этот get()метод следующим образом:
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!");
}
}
Обратите внимание , что в этом случае created
функция ПОТРЕБНОСТЕЙ быть async
, так как get()
асинхронный.
Подробнее о разнице между get()
и onSnapshot()
в этом SO-ответе .
попробуйте использовать функцию стрелки
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)
},