Безуспешно ждут, чтобы получить субколлекцию - PullRequest
0 голосов
/ 27 мая 2019

Я попробовал подходы await / async для получения коллекции, связанной с моим документом Firebase. Данные извлекаются и журнал отладки выводится на консоль; однако, это после того, как вызывающая функция вернулась. Любая помощь будет оценена. Я использовал документацию Angular Firestore: https://github.com/angular/angularfire2/blob/master/docs/firestore/collections.md

Я использую подписку на данные и попытался дождаться снимка

// Client call
async doSearch() {
const col = await this.service.getLogbookEntries(this.searchDoc.id)
      .then(entries => {
        for (let i = 0; i < entries.length; i++) {
          // Do something with entry
          const entry = entries[0];
        }
      });
}

// Collection retrieval
async getLogbookEntries(docId: string): Promise<LogbookEntry[]>
  // Retrieve sub collection and convert
  return new Promise((resolve) => {
    const entries: LogbookEntry[] = [];
    console.log("Retrieving logbook entries: ", docId);
    const doc = this.db.doc(`${this.endpoint}/${docId}`);
    doc.collection<Usage>("Usage").snapshotChanges()
      .subscribe(async a => {
          for (let i = 0; i < a.length; i++) {
            let data = a[i].payload.doc.data(); 
            let id = a[i].payload.doc.id;
            console.log("Cleaning ID: ", id, " Data: ", data);
            entries.push(this.toLogbookEntry(id, data);
          }
          resolve(entries);
        });
    });

Клиентский вызов возвращается, даже если ожидание вернулось.

Обновление Я смог получить должное ожидание, основываясь на следующем:

  async getLogbookEntries(docId: string): Promise<LogbookEntry[]> {
    const entries: LogbookEntry[] = [];
    console.log("Retrieving logbook entries: ", docId);
    const doc = this.db.doc(`${this.endpoint}/${docId}`);
    // Explicitly convert to promise.
    const cleaningCol = await doc.collection<ICleaning>("cleanings").get().toPromise();
    const cleaningsChanges = cleaningCol.docChanges();
    for (let i = 0; i < cleaningsChanges.length; i++) {
      const id = cleaningsChanges[i].doc.id;
      const data = cleaningsChanges[i].doc.data();
      console.log("Cleaning: ", data);
      entries.push(this.toLogbookEntry(id, LogbookType.Cleaning, data as ICleaning));
    }

1 Ответ

0 голосов
/ 27 мая 2019

Основная причина вашей проблемы заключается в том, что вы смешиваете понятие подписки на данные в вашем документе Firebase и извлечения данных в вашем документе Firebase (используя async / await). Вам нужно будет провести рефакторинг этого решения, используя один или другой шаблон (подписка или шаблон асинхронной выборки).

    doSearchOnChanges() {
    const col = await this.service.getLogbookEntries(this.searchDoc.id, doStuffAfterRetrieval)
      function doStuffAfterRetrieval = entries => {
        for (let i = 0; i < entries.length; i++) {
          // Do something with entry
          const entry = entries[0];
        }
      };
     }

 // Collection retrieval
 getLogbookEntries(docId: string, doStuff: entry => void): void
  // Retrieve sub collection and convert
    const entries: LogbookEntry[] = [];
    console.log("Retrieving logbook entries: ", docId);
    const doc = this.db.doc(`${this.endpoint}/${docId}`);
    doc.collection<Usage>("Usage").snapshotChanges()
      .subscribe(async a => {
          for (let i = 0; i < a.length; i++) {
            let data = a[i].payload.doc.data(); 
            let id = a[i].payload.doc.id;
            console.log("Cleaning ID: ", id, " Data: ", data);
            entries.push(this.toLogbookEntry(id, data);
          }
          doStuff(entries);
        });

Это более или менее то, как вы бы преобразовали свой код в правильное использование подписки. Я не очень знаком с API Firebase, но при беглом поиске в Google, чтобы получать данные, а не подписываться на них, вам нужно использовать функцию .get() в коллекциях. (Также ProTip: Никогда не используйте .hen, когда вы используете async / await. Это избыточно и приведет к ошибкам чаще, чем нет. Выберите один шаблон и придерживайтесь его.)

async doSearch() {
  const col = await this.service.getLogbookEntries(this.searchDoc.id);
  for (let i = 0; i < col.length; i++) {
    // Do something with entry
    const entry = entries[0];
  }
}

// Collection retrieval
async getLogbookEntries(docId: string): Promise<LogbookEntry[]> {
  // Retrieve sub collection and convert
  // Don't create your own promises. Async/Await and the Firbase API will do this for you
    const entries: LogbookEntry[] = [];
    console.log("Retrieving logbook entries: ", docId);
    const doc = this.db.doc(`${this.endpoint}/${docId}`);
    const returnedData = await doc.collection<Usage>("Usage").get();
    for (let i = 0; i < returnedData.length; i++) {
      let data = returnedData[i].payload.doc.data();
      let id = returnedData[i].payload.doc.id;
      console.log("Cleaning ID: ", id, " Data: ", data);
      entries.push(this.toLogbookEntry(id, data));
    }
    return entries;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...