首页 文章

无法使用promise在阵列中“捕获”Firebase快照

提问于
浏览
2

我知道使用Javascript promises加载返回的Firebase对象有很多问题和答案,但我没有成功捕获数组中的数据 .

The issue: 我已经设置了一个数组(下面的 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());
    });
  });
}

Question: 我认为我使用 Promise.all 错误,但无法弄清楚如何(也是新的异步函数) . 感谢您提供有关如何成功加载 productArray 的任何提示 .

Edit: 为了详细说明,似乎 snapshot 正在加载正确的Firebase数据,并且 forEach 正确循环遍历 snapshot 中的每个项目,但 productArrayPromise.all 语句之外变为(或保持)为空 .

Update 我实现了下面的所有建议,然而,程序将不会停留足够长的时间来从快照对象构建数组 . 去年我使用了Angularfire的 $loaded 函数,它在程序等待方面非常有效,所以我不明白为什么普通的JS promise 在这里不起作用 . 诉诸 timeout 是否有意义?我甚至试图结合alexmac _2883431的建议,但没有雪茄:

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();
}

2 回答

  • 1

    一个工作示例可能如下所示:

    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);
    }
    

    在这里,我使用promisification为 firebase 查询创建一个承诺 . 所以 loadFBData 返回一个promise,我可以创建一个promise链或使用ES7 async / await等到promise将被用来使用result .

  • 0

    背景

    我认为你错过了对promises和Firebase SDK的理解 .

    首先,请注意所有Firebase SDK函数都会返回promise,因此无需创建自己的函数 . 其次,Promise.all是为了结合多个承诺 . 单个承诺可以通过简单的 .then() 链接起来 .

    我在这里有关于保存和查询数据的视频:Save and Query Firebase Data

    我在这里有另一个关于承诺的视频:Promises

    加载Firebase

    您应该在页面的顶部初始化firebase . 它只需要初始化一次,所以不要在函数内初始化它 .

    您可以在页面上加载Firebase SDK后立即致电 firebase.initializeApp(config) . 或者您可以参考Firebase Hosting的 init.js ,如下所示 .

    示例

    以下示例加载Firebase SDK,使用我的测试db的 init.js 文件初始化firebase,然后查询,操作并返回一个数组 .

    请注意,Firebase不支持零索引数组,因此从Firebase返回的所有内容都将是未分类的对象 . 这个例子显示了一些返回数据的不同方法:)

    <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>
    

相关问题