从 Firebase 数据库读取整个节点

Read whole node from Firebase Database

类别:

数据库:

我正在尝试读取整个选定节点(类别),然后过滤它们并 return 在云可调用函数中过滤它们。如何获取所有数据然后对其进行过滤?当我尝试记录数组时,它是空的。

exports.getRecipes = functions.region('europe-west1').https.onCall((data, context) => {

    categories = data.categories;



    eventsData = [];

    for (let i = 0; i < categories.length; i++) {
        admin.database().ref(categories[i]).once('value', (data) => {
            eventsData.push(data.val());
        });
    }

    console.log(eventsData);


    return "hello";

});

是否有任何其他方法使用 admin.database().ref() 而不使用 .once() 获取整个节点?

数据是从 Firebase(和大多数现代云 API)异步加载的,在加载数据的同时,您的其余代码会继续 运行。如果您在代码中添加一些日志记录,这是最容易看到的:

console.log("Before starting to load data")

for (let i = 0; i < categories.length; i++) {
    admin.database().ref(categories[i]).once('value', (data) => {
        console.log("Got data")
    });
}

console.log("After starting to load data")

当你运行这段代码时,输​​出是:

Before starting to load data

After starting to load data

Got data

Got data

...

这可能是您期望输出的顺序,但它解释了为什么您的 console.log(eventsData) 显示一个空数组:在您记录数组时,数据的 none已经加载,eventsData.push(data.val()) 还没有 运行。


这个问题的解决方案总是相同的:任何需要异步调用数据的代码都需要直接在回调中,从那里调用,或者以其他方式同步。

由于您正在加载多个节点,我们将在此处使用 Promise.all 来等待所有这些节点都已加载。

exports.getRecipes = functions.region('europe-west1').https.onCall((data, context) => {
    const categories = data.categories;
    const eventsData = Promise.all(categories.map((category) => {
        return admin.database().ref(categories[i]).once('value').then((snapshot) => {
            return snapshot.val();
        });
    });

    return eventsData;
});

由于我们现在 return 一个承诺,Cloud Functions 将等待该承诺得到解决,然后 return 将结果值提供给调用方。

我建议在以下位置了解有关承诺和异步行为的更多信息: