Firebase在加载视图之前未接收数据 - 填充之前返回空数组

时间:2017-05-09 19:21:12

标签: javascript angular firebase callback firebase-realtime-database

在下面的代码中,我将每个项目的密钥和一个电子邮件地址保存在一个表中,并使用所述密钥检索要从原始表中获取的对象。我可以看到,当我在console.log中时,这些项目被放入rawList数组中,但是函数在它有任何内容之前返回this.cartList,因此视图没有收到任何内容的数据。如何才能使this.cartList在返回之前等待rawList已满?

 ionViewWillEnter() {
    var user = firebase.auth().currentUser;
    this.cartData.getCart().on('value', snapshot => {
        let rawList = [];
        snapshot.forEach(snap => {
          if (user.email == snap.val().email) {
            var desiredItem = this.goodsData.findGoodById(snap.val().key);
            desiredItem.once("value")
            .then(function(snapshot2) {
              rawList.push(snapshot2);
            });
            return false
          }
        });
        console.log(rawList);
        this.cartList = rawList;
    });
  }

我已经尝试将this.cartList = rawList放在许多不同的位置(return false之前,甚至在.then语句中,但这并没有解决问题。

3 个答案:

答案 0 :(得分:1)

问题是forEach循环(sync)中的Promise(对firebase的异步.once()调用)。 forEach循环不会等待then()语句,所以在下一次迭代中,上一次迭代的数据就丢失了......



let snapshots = [1, 2, 3];
let rawList = [];

snapshots.forEach((snap) => {
  console.log(rawList.length)
  fbCall = new Promise((resolve, reject) => {
    setTimeout(function() {
      resolve("Success!");
    }, 2500)
  });
  fbCall.then((result) => {
    rawList.push(result);
  });
})




你需要forEach将整个Promise推送到rawList然后等待它们解决并做结果。



var snapshots = [1, 2, 3];
var rawList = [];
var counter = 0;

snapshots.forEach((snap) => {
  console.log(rawList.length)
  var fbCall = new Promise((resolve, reject) => {
    setTimeout(function() {
      resolve("Success!" + counter++);
    }, 1500)
  });
  rawList.push(fbCall);
})

Promise.all(rawList).then((res) => {
  console.log(res[0]);
  console.log(res[1]);
  console.log(res[2]);
});




问题是,分配this.cartList = Promise.all(rawList)仍然有点尴尬,因为它使它成为一个Promise。那么您可能想重新考虑您的设计并制作类似于getCartList服务的东西? (不知道你的app是什么样的:p)

答案 1 :(得分:1)

由于你正在使用角度,你也应该使用angularfire2,它会使用Observables来解决这个问题。您仍然会使用常规SDK进行许多操作,但是为了获取和绑定数据,建议不要在没有angularfire2的情况下单独使用Firebase,因为这会使这些事情变得不易管理。

这种方法的好处在于您可以利用Observable上的任何方法,例如filterfirstmap等。

安装后,只需执行:

public items$: FirebaseListObservable<any[]>;

this.items$ = this.af.database.list('path/to/data');

在视图中:

{{items$ | async}}

等待数据出现。

答案 2 :(得分:0)

使用AngularFire2RxJS这将为您节省大量时间,并且您将通过使用RxJS运算符以正确且可维护的方式执行此操作,您可以在此处了解这些运算符{{ 3}}