从 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 将结果值提供给调用方。
我建议在以下位置了解有关承诺和异步行为的更多信息:
- 关于终止函数的 Firebase 文档:Sync, async, and promises。
- Doug 在 Learn JavaScript Promises (Pt.1) with HTTP Triggers in Cloud Functions
上的视频系列
- Asynchronous JavaScript
上的 MDN 页面
类别:
数据库:
我正在尝试读取整个选定节点(类别),然后过滤它们并 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 将结果值提供给调用方。
我建议在以下位置了解有关承诺和异步行为的更多信息:
- 关于终止函数的 Firebase 文档:Sync, async, and promises。
- Doug 在 Learn JavaScript Promises (Pt.1) with HTTP Triggers in Cloud Functions 上的视频系列
- Asynchronous JavaScript 上的 MDN 页面