从Firebase读取嵌套数据会返回数组以外的内容

时间:2019-04-13 21:47:01

标签: javascript arrays firebase firebase-realtime-database

尝试读取(并期望)像这样的嵌套数组:

var array = [
0: {subArrayy: {...}, title: "Title"}, 
1: {subArray]: {...}, title: "Title"},
...

但是,在读取和(!)输出之后,结果还是不错的。我的Web控制台向我显示了阵列,一切似乎都很好。但是执行array.length返回0。任何迭代都返回undefined。

我已经尝试使用我之前见过的ladosh _.toArray东西,但是它绝对没有作用。

var locations = []; // Empty array

  var ref = db.ref("locations/");
  ref.once("value", function(snapshot) {

    snapshot.forEach(function(item) {
      var itemVal = item.val();
      locations.push(itemVal); // Adding new items seems to work at first

    });

  });
  console.log(locations, locations.length);

输出:

chrome output

我希望它是可迭代的,因为我可以使用数组0进行导航。

3 个答案:

答案 0 :(得分:0)

放置睡眠功能约300毫秒似乎可以解决此问题。我认为这与同步有关,尽管并不完全确定。我想这只需要一些时间来处理查询并分配所有内容。

答案 1 :(得分:0)

Firebase异步读取数据,因此在等待网络流量时不会阻止该应用程序。然后,一旦数据被加载,它将调用您的回调函数。

通过放置一些日志语句,您可以轻松地看到这一点:

console.log("Before starting to load data");
ref.once("value", function(snapshot) {
  console.log("Got data");
});
console.log("After starting to load data");

运行此代码时,输​​出为:

  

开始加载数据之前

     

开始加载数据后

     

获得数据

这可能不是您期望的顺序,但是它准确地解释了为什么在记录日志时会得到零长度的数组。但是由于主代码会立即继续,所以到您console.log(locations, locations.length)数据还没有加载,并且还没有将其推送到数组时。


解决方案是确保所有需要数据的代码都在回调内部,或者从那里调用。

这将起作用:

var locations = []; // Empty array

var ref = db.ref("locations/");
ref.once("value", function(snapshot) {

  snapshot.forEach(function(item) {
    var itemVal = item.val();
    locations.push(itemVal);
  });

  console.log(locations, locations.length);

});

这将是

function loadLocations(callback) {
  var locations = []; // Empty array

  var ref = db.ref("locations/");
  ref.once("value", function(snapshot) {
    snapshot.forEach(function(item) {
      var itemVal = item.val();
      locations.push(itemVal);
    });
    callback(locations);
  });
});

loadLocations(function(locations) {
  console.log(locations.length);
});

最后一个代码段的一个更现代的变体是返回一个promise,而不是传递回调。

function loadLocations() {
  return new Promise(function(resolve, reject) {
    var locations = []; // Empty array

    var ref = db.ref("locations/");
    ref.once("value", function(snapshot) {
      snapshot.forEach(function(item) {
        var itemVal = item.val();
        locations.push(itemVal);
      });
      resolve(locations);
    });
  })
});

然后您可以这样称呼它:

loadLocations().then(function(locations) {
  console.log(locations.length);
});

或者使用现代JavaScript,您可以使用async / await并执行以下操作:

let locations = await loadLocations()
console.log(locations.length);

请记住,最后一个代码片段仍然具有相同的异步行为,并且JavaScript运行时(或编译器)只是向您隐藏了它。

答案 2 :(得分:0)

使用等待读取功能似乎也有帮助。