Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 不能;捕获“;使用promise的阵列中的Firebase快照_Javascript_Firebase_Firebase Realtime Database_Promise - Fatal编程技术网

Javascript 不能;捕获“;使用promise的阵列中的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

我知道在使用Javascript承诺加载返回的Firebase对象方面有很多问题和答案,但我还没有成功地捕获数组中的数据

问题:我已经设置了一个数组(
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
函数,该函数非常有效地让程序等待,因此我不明白为什么普通的JS
promise
在这里不起作用。诉诸
超时
有意义吗?我甚至尝试结合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>