Получить коллекцию + подколлекция даст мне пустой рендер - PullRequest
0 голосов
/ 17 июня 2019

Проблема

При запуске веб-приложения основной задачей является получение всей пользовательской информации, которая хранится в различных коллекциях и вложенных коллекциях Firestore.

Проблема в том, что даже еслиЯ использую обещания и состояние загрузки, чтобы предотвратить рендеринг пустого приложения, приложение отображается со всеми данными коллекций, за исключением коллекций, которые имеют вложенные коллекции.

Процесс

- If user is logged 
-- Set Loading Status Active
-- Load Collection A
-- Load Collection B and forEach, load all sub-collection
-- Load Collection C
-- Set Loading Status Inactive

Вна этом этапе приложение отображается, но только с коллекцией A и коллекцией C. коллекция B загружена (я вижу это по журналам Redux), но не может быть видна в приложении.

Эти данные появляются, только если я изменяю статус компонента (например, открываю / закрываю меню).

Некоторый код

Вот как я могу получить коллекцию с вложенными коллекциями:


export function setCompanyJobs(user) {

    return {
        type: "SET_COMPANY_JOBS",
        payload: loadCompanyJobs(user),
    };
}

Функция, которая извлекает основную коллекцию


export function loadCompanyJobs(user) {

    return new Promise((resolve, reject) => {

        let companyJobs = [];

        db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {


            jobs.forEach((job) => {

                loadJobLinkedServices(user, job).then((jobLinkedServices) => {

                    companyJobs.push({
                        id:     job.id,
                        ...

                    });
                });

            });

            resolve(companyJobs);

        }).catch(function (error) {

            ...
        });
    });
}

Функциякоторые извлекают все коллекции коллекции

export function loadJobLinkedServices(user, job){

    return new Promise((resolve, reject) => {

        let jobLinkedServices = [];
        db.collection("company").doc(user.selectedCompany).collection("jobs").doc(job.id).collection("linkedServices").get().then((linkedServices) => {

            linkedServices.forEach((linkedService) => {

                jobLinkedServices.push({

                    id:         linkedService.id,
                    ...
                });

            });

            resolve(jobLinkedServices)

        }).catch(function (error) {

            ...
        });
    })

1 Ответ

2 голосов
/ 17 июня 2019

Когда вы делаете

return new Promise((resolve, reject) => {

    let companyJobs = [];

    db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {


        jobs.forEach((job) => {

            loadJobLinkedServices(user, job).then((jobLinkedServices) => {

                companyJobs.push({
                    id:     job.id,
                    ...

                });
            });

        });

        resolve(companyJobs);

    }).catch(function (error) {

        ...
    });
});

ничто не гарантирует, что ваше Обещание разрешается только после того, как ВСЕ запросы, запущенные в цикле jobs.forEach(), выполнены (т. Е. Обещания, возвращаемые вызовами функции loadJobLinkedServices, разрешены).

Я не знаю responsejs, но я думаю, что вы можете использовать метод JavaScript Promise.all() в следующих строках:

return new Promise((resolve, reject) => {


    let promises = [];

    let companyJobs = [];

    db.collection("company").doc(user.selectedCompany).collection("jobs").get().then((jobs) => {


        jobs.forEach((job) => {

            promises.push(loadJobLinkedServices(user, job));

        });

        Promise.all(promises).
        then(results => {
          //Loop over the results array to populate the companyJobs array
           resolve(companyJobs);
        })

    }).catch(function (error) {

        ...
    });
});

Кроме того, не забудьте правильно связать ваши вызовы с различными асинхронными функциями, например что-то вроде:

query Collection A
THEN query Collection B
THEN query all sub-collections (with Promise.all())
THEN query Collection C
THEN set Loading Status Inactive

Наконец, последнее замечание: обратите внимание, что метод get() возвращает обещание, поэтому я не уверен, что вам нужно заключить вызовы метода get() в какой-то новый Promises (Опять же, я не разбираюсь в реакциях, поэтому это замечание может быть ошибочным).

Другими словами, я думаю, что вы могли бы сделать что-то вроде следующего (например, для функции loadJobLinkedServices):

export function loadJobLinkedServices(user, job){

         let jobLinkedServices = [];
         return db.collection("company").doc(user.selectedCompany).collection("jobs").doc(job.id).collection("linkedServices").get()
        .then((linkedServices) => {

            linkedServices.forEach((linkedService) => {

                jobLinkedServices.push({

                    id:         linkedService.id,
                    ...
                });

            });

            return jobLinkedServices;

        }).catch(function (error) {

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