База данных React-native-firebase - извлекает данные из вложенных вызовов - PullRequest
0 голосов
/ 21 октября 2018

У меня есть база данных Firebase как таковая (например):

{
    'itemCategories': [
        _categoryKey1: {
            name: 'Category 1'
        },
        _categoryKey2: {
            name: 'Category 2'
        },
        _categoryKey3: {
            name: 'Category 3'
        },
    ],
    'items': [
        _itemKey1: {
            categoryId: '_categoryKey1',
            name: 'Item 1',
        }
        _itemKey2: {
            categoryId: '_categoryKey2',
            name: 'Item 2',
        }
        _itemKey3: {
            categoryId: '_categoryKey1',
            name: 'Item 3',
        }
        _itemKey4: {
            categoryId: '_categoryKey3',
            name: 'Item 4',
        }
        _itemKey5: {
            categoryId: '_categoryKey3',
            name: 'Item 5',
        }
    ]
}

Я хочу получить массив элементов, сгруппированных по категориям, например:

itemList = [
    {
        category: 'Category 1',
        items: [
            {
                id: '_itemKey1',
                categoryId: '_categoryKey1',
                name: 'Item 1',
            },
            {
                id: '_itemKey3',
                categoryId: '_categoryKey1',
                name: 'Item 3',
            }
        ]
    },
    {
        category: 'Category 2',
        items: [
            {
                id: '_itemKey2',
                categoryId: '_categoryKey2',
                name: 'Item 2',
            }
        ]
    },
    {
        category: 'Category 3',
        items: [
            {
                id: '_itemKey4',
                categoryId: '_categoryKey3',
                name: 'Item 4',
            },
            {
                id: '_itemKey5',
                categoryId: '_categoryKey3',
                name: 'Item 5',
            },
        ]
    },
]

Для этого я использую действие react-redux, например:

export const setItemList = (list) => {
    return {
        type: 'setItemList',
        value: list
    }
}

export const getItemListByCategory = () => {
    return (dispatch) => {

        let itemList = []

        firebase.database().ref('itemCategories').on('value', (snapCategory) => {
            snapCategory.forEach((category) => {
                const categoryId = category.key

                firebase.database().ref('items').orderByChild('categoryId').equalTo(categoryId).on('value', (snapItem) => {
                    let items = []
                    snapItem.forEach((item) => {
                        items.push({
                            id: item.key,
                            ...item.val()
                        })
                    })

                    itemList.push({
                        category: category.val().name,
                        items: items
                    })

                    // This is where I think is the issue
                    dispatch(setItemList(itemList))
                })
            })

            // The dispatch should be there, when every calls resolved
        })
    }
}

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

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

1 Ответ

0 голосов
/ 22 октября 2018

Как насчет использования Promise.all ()?Вместо запуска диспетчеризации в firebase.database().ref('items').orderByChild('categoryId').equalTo(categoryId).on Вы можете добавить этот вызов в массив обещаний.Как то так:

const promises = [];

snapCategory.foreach(snap => {

   promises.push(your calls here, instead of dispatch return the list here)
}) 

Promise.all(promises).then((...args) => {
// args should contain all lists here, you can manipulate them as you need
// and dispatch afterwards
})
...