Javascript 不能;捕获“;使用promise的阵列中的Firebase快照
我知道在使用Javascript承诺加载返回的Firebase对象方面有很多问题和答案,但我还没有成功地捕获数组中的数据 问题:我已经设置了一个数组(Javascript 不能;捕获“;使用promise的阵列中的Firebase快照,javascript,firebase,firebase-realtime-database,promise,Javascript,Firebase,Firebase Realtime Database,Promise,我知道在使用Javascript承诺加载返回的Firebase对象方面有很多问题和答案,但我还没有成功地捕获数组中的数据 问题:我已经设置了一个数组(productArray如下),以迭代方式获取Firebase快照的值,但退出forEach循环后,该数组仍然为空 database.js: getProductList = function(){ let productArray =[]; loadFBData = function(){ firebase.i
productArray
如下),以迭代方式获取Firebase快照的值,但退出forEach
循环后,该数组仍然为空
database.js:
getProductList = function(){
let productArray =[];
loadFBData = function(){
firebase.initializeApp(config);
return firebase.database().ref().once("value", function(snapshot){
return snapshot.val();
});
}
Promise.all([loadFBData()]).then(function(snapshot) {
snapshot.forEach(function(product) {
productArray.push(product.val());
});
});
}
问题:我想我使用的是Promise。所有的都是错误的,但无法理解如何使用(也是新的异步函数)。感谢您提供有关如何使productArray
成功加载的提示
编辑:要详细说明,似乎snapshot
正在加载正确的Firebase数据,forEach
在snapshot
中的每个项目都正确循环,但是productArray
在承诺之外变为(或保持)空
更新我实现了下面的所有建议,但程序不会停止太久,无法从快照对象构建数组。去年我使用了Angularfire的$loaded
函数,该函数非常有效地让程序等待,因此我不明白为什么普通的JSpromise
在这里不起作用。诉诸超时
有意义吗?我甚至尝试结合alexmac和Pointy的建议,但没有雪茄:
getProductList = function(){
let productArray =[];
loadFBData = function(){
firebase.initializeApp(config);
return new Promise(resolve => {
firebase.database().ref().once('value')
.then(function(snapshot){
return resolve(function(snapshot){
productArray = Object.keys(snapshot).map((key, prod) => prod);
});
});
});
}
loadFBData();
}
工作示例可能如下所示:
getProductList = () => {
let loadFBData = () => {
firebase.initializeApp(config);
return new Promise(resolve => {
firebase.database().ref().once('value', resolve);
});
}
let productArray =[];
loadFBData()
.then(snapshot => {
productArray = Object.keys(snapshot).map((key, prod) => prod);
}
在这里,我使用Promission为firebase
查询创建承诺。所以loadFBData
返回一个承诺,我可以创建一个承诺链,或者使用ES7 async/await等待,直到承诺实现后才能使用结果。Background
我认为您对promises和Firebase SDK都缺乏了解
首先,请注意,所有Firebase SDK函数都返回承诺,因此无需创建自己的函数。第二,承诺。一切都是为了组合多个承诺。用一个简单的.then()
,就可以把一个承诺拴起来
我这里有一个关于保存和查询数据的视频:
我这里还有一个关于承诺的视频:
装载火基
您应该在页面顶部初始化firebase。它只需要初始化一次,所以不要在函数中初始化它
您可以在页面上加载firebase SDK后调用firebase.initializeApp(config)
。或者您可以参考Firebase主机的init.js
,如下所示
例子
下面的示例加载Firebase SDK,使用我的测试db的init.js
文件初始化Firebase,然后查询、操作并返回一个数组
请注意,Firebase不支持零索引数组,因此从Firebase返回的所有内容都将是未排序的对象。此示例显示了返回数据的几种不同方式:)
函数loadFirebaseArray(路径){
返回firebase.database().ref(path).one('value')。然后返回(snap=>snap.val());
}
功能到阵列(项目){
返回Object.key(items).reduce((数组,key)=>{
常量值=项[键];
push({key,value});
返回数组;
},[]).sort();
}
loadFirebaseArray('stackoverflow')。然后(项=>{
console.log('items',items);
const asArray=toArray(项目);
警报(JSON.stringify(asArray));
const justTheValues=asArray.map(x=>x.value.sort();
警报(仅限值);
});
乍一看,此代码看起来不错。它将只使用一个承诺,因为您正在加载整个数据库。但这应该行得通,除非我忽略了什么。这个密码有什么问题吗?@Frank,谢谢你的回复。更详细地说,snapshot
确实正在加载Firebase数据。问题是(或必须是)在forEach
循环中,因为(就在Promise.all
之后和getProductList()
的内部,productArray.length
返回0。您的代码实际上根本没有做出承诺。loadFBData()
函数需要在Promise回调中使用当前代码返回新的Promise。函数应将检索到的数据传递给resolve()
函数。为什么要使用Promise。所有仅用于一个元素?另外,如果firebase.database().ref()。一旦
返回一个承诺,你根本不需要promise.all
。@alexmac-你说得对,我也刚刚解决了这个问题(从另一个SO答案中复制了此解决方案-但不了解此用法。谢谢,我目前正在尝试ES6解决方案,并试图解决为什么我得到Uncaught(承诺)类型错误:snapshot.map不是一个函数
Add breakpoint或console.log(快照)
在productArray=snapshot
之前,检查什么是snapshot
。根据您的代码,它必须是一个数组。snapshot
由一个JSON对象填充,该对象看起来是典型的Firebase格式:{“key”:{…},“key”:{…},}
。其中key
是(在我的例子中)表示整数的字符串。我想知道这个对象是否太深了,但实际上只有两个级别:key和{obj}。无论如何,快照是一个对象而不是数组。我正在尝试遍历快照对象中的每个项,并将它们添加/推送到数组中。但是如果你说检索到的快照应该是一个数组,那么我可能在这里处理完全不同的蠕虫。更新了答案,通过gh快照
属性。
<html>
<head>
<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
<script src="https://quiver-two.firebaseapp.com/__/firebase/init.js"></script>
<script>
function loadFirebaseArray(path) {
return firebase.database().ref(path).once('value').then(snap => snap.val());
}
function toArray(items) {
return Object.keys(items).reduce((array, key) => {
const value = items[key];
array.push({key, value});
return array;
}, []).sort();
}
loadFirebaseArray('stackoverflow').then(items => {
console.log('items', items);
const asArray = toArray(items);
alert(JSON.stringify(asArray));
const justTheValues = asArray.map(x => x.value).sort();
alert(justTheValues);
});
</script>
</head>
</html>