Tunggu hingga firebase selesai memuat data (vue) / 'await' tidak berfungsi

Jan 11 2021

Di aplikasi vue saya, saya mengambil beberapa data dari firebase di created-hook. Saya ingin kode setelah itu dieksekusi setelah data selesai dengan pemuatan. Tapi saya tidak bisa membuatnya berhasil.

Ini kode saya:

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

Tapi satu konsol, pertama 'Done with fetching Data'ditampilkan, kemudian null(karena this.settingsmasih null) dan hanya setelah itu Objekt settingsdicetak. Tapi saya perlu this.settingsdidefinisikan di sana (dan tidak nulllagi) untuk bekerja di sana.

Apa yang saya coba sejauh ini:

  1. Menempatkan menunggu
  2. Menambahkan file parameter
  3. Menambahkan kode setelahnya di a then()

Tidak ada yang berhasil.

Jawaban

3 RenaudTarnec Jan 11 2021 at 00:56

The onSnapshot()Metode bukanlah metode asynchronous. Seperti yang dijelaskan di dokumen, itu "melampirkan pendengar untuk DocumentSnapshotacara".

Jadi, Anda harus menggunakannya jika Anda ingin menyetel pendengar berkelanjutan ke dokumen Firestore: jika ada perubahan dalam dokumen (misalnya, bidang mendapat nilai baru) pendengar akan dipicu. Perhatikan bahwa "panggilan awal menggunakan callback yang Anda berikan membuat snapshot dokumen segera dengan konten saat ini dari satu dokumen" (lihat dokumen ).

Anda mendapatkan data dokumen Firestore hanya dalam fungsi callback yang Anda teruskan onSnapshot(), sebagai berikut:

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

Seperti yang disebutkan Nilesh Patel, perhatikan bahwa Anda perlu menggunakan fungsi panah untuk menggunakan thispanggilan balik ini . Perhatikan juga bahwa createdfungsinya TIDAK perlu async .

Terakhir, perhatikan bahwa praktik yang baik adalah memanggil fungsi unsubscribe yang ditampilkan onSnapshot()saat Anda memusnahkan komponen Vue.js. Gunakan beforeDestroypengait sebagai berikut:

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

Di sisi lain, jika Anda hanya ingin membaca data dokumen HANYA SEKALI di hook Vue.js yang dibuat, Anda harus menggunakan get()metode berikut:

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

Perhatikan bahwa, dalam kasus ini, createdfungsi PERLU menjadi async, karena get()asynchronous.


Lebih detail tentang perbedaan antara get()dan onSnapshot()dalam jawaban SO ini .

1 NileshPatel Jan 11 2021 at 00:46

coba gunakan fungsi panah

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