Poczekaj, aż Firebase zakończy ładowanie danych (vue) / 'await' nie działa

Jan 11 2021

W mojej aplikacji vue createdpobieram dane z Firebase w -hook. Chcę, aby kod był później wykonywany po zakończeniu ładowania danych. Ale nie mogę sprawić, żeby to zadziałało.

Oto mój kod:

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

Ale najpierw konsola 'Done with fetching Data'jest wyświetlana, potem null(ponieważ this.settingsjest nieruchoma null) i dopiero potem settingsdrukowany jest Objekt . Ale muszę this.settingsbyć tam zdefiniowany (i nulljuż nie ), aby tam pracować.

Co próbowałem do tej pory:

  1. Wstawianie czeka
  2. Dodanie załadowanego pliku parameter
  3. Dodanie kodu później w pliku then()

Nic nie działało.

Odpowiedzi

3 RenaudTarnec Jan 11 2021 at 00:56

onSnapshot()Metoda nie jest metodą asynchroniczny. Jak wyjaśniono w dokumencie, „dołącza nasłuchiwanie DocumentSnapshotzdarzeń”.

Dlatego powinieneś go użyć, jeśli chcesz ustawić ciągły nasłuchiwanie dokumentu Firestore: jeśli coś się zmieni w dokumencie (np. Pole otrzyma nową wartość), detektor zostanie wyzwolony. Zwróć uwagę, że „pierwsze połączenie przy użyciu dostarczonego przez Ciebie wywołania zwrotnego tworzy natychmiast migawkę dokumentu z bieżącą zawartością pojedynczego dokumentu” (zobacz dokumentację ).

Dane dokumentu Firestore uzyskujesz tylko w funkcji wywołania zwrotnego, do której przekazujesz onSnapshot(), w następujący sposób:

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

Jak wspomniał Nilesh Patel, pamiętaj, że musisz użyć funkcji strzałki, aby użyć thistego wywołania zwrotnego . Należy również pamiętać, że createdfunkcja NIE musi być asynchroniczna .

Na koniec zwróć uwagę, że dobrą praktyką jest wywołanie funkcji anulowania subskrypcji zwracanej onSnapshot()po zniszczeniu komponentu Vue.js. Użyj beforeDestroyhaka w następujący sposób:

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

Z drugiej strony, jeśli chcesz po prostu odczytać dane dokumentu TYLKO RAZ w utworzonym hooku Vue.js, powinieneś użyć następującej get()metody:

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

Zauważ, że w tym przypadku createdfunkcja MUSI być async, ponieważ get()jest asynchroniczna.


Więcej szczegółów na temat różnicy między get()iw onSnapshot()tej odpowiedzi TAK .

1 NileshPatel Jan 11 2021 at 00:46

spróbuj użyć funkcji strzałek

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