Функции Firebase: есть ли способ асинхронно перебирать несколько коллекций? - PullRequest
0 голосов
/ 09 февраля 2019

При написании API я хотел собрать коллекцию объектов и извлечь каждый из их атрибутов.Один атрибут - это коллекция внутри каждого объекта.Однако, похоже, что <QuerySnapshot> не поддерживает асинхронную итерацию.

Псевдокод (с использованием TypeScript):

let objects = [];
const objectSnapshot = await admin.firestore().collection('object').get();

objectSnapshot.forEach(async (objectDoc) => {
    let values = [];
    const valueSnapshot = await admin.firestore().collection('object').doc(objectDoc.id).collection('value').get();

    valueSnapshot.forEach((valueDoc) => {
        values.push(valueDoc.data());
    });

    objects.push(values);
});

return objects;

Следующий код не ожидает objects Заполняется и ничего не возвращает.

Есть предложения?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Проблема в том, что forEach сам по себе не работает синхронно, поэтому вы возвращаете объекты до того, как у них появится возможность их заполнения.

У вас есть несколько вариантов решения этой проблемы, в вашем случае я бырекомендуем вернуть массив обещаний и дождаться их окончания, прежде чем вернутьсяКак то так:

const objectSnapshot = await admin.firestore().collection('object').get();

// Creates an array of promises that can be awaited later
// You can use the docs property which is an array, and then you can use map on it
const promises = objectSnapshot.docs.map(async (objectDoc) => {
    // This will execute in parallel but will create a promise and add it to promises
    const valueSnapshot = await admin.firestore().collection('object').doc(objectDoc.id).collection('value').get();
    return valueSnapshot.docs.map((valueDoc) => valueDoc.data());
});

// Wait for all promises created before returning
return await Promise.all(promises);
0 голосов
/ 09 февраля 2019

Ошибка, которую вы делаете здесь, заключается в том, что обратный вызов, который вы передаете forEach, не должен быть помечен как асинхронный.Все асинхронные функции немедленно возвращают обещание, которое разрешается, когда все остальные ожидаемые асинхронные работы в функции завершены.Это означает, что forEach собирается быстро выполнить все эти обещания , не дожидаясь их разрешения .После завершения итерации асинхронная работа внутри каждого обратного вызова будет завершена.Это не совсем то, как вы хотите использовать forEach.

Если вы хотите выполнить некоторую асинхронную работу для каждого снимка документа и собрать результаты всей этой асинхронной работы, вы должны вместо этого выполнить итерацию массива документов в objectSnapshot.docs.Затем вы можете выполнить дополнительную асинхронную работу для каждого документа.Идиоматически для JavaScript, используйте функцию массива map(), чтобы преобразовать массив снимков документа в массив обещаний.Затем вы можете использовать Promise.all() в этом массиве обещаний, чтобы дождаться завершения всей работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...