【问题标题】:Firebase - Retrieving and storing data in array with callbacksFirebase - 使用回调检索和存储数组中的数据
【发布时间】:2018-11-23 17:00:46
【问题描述】:

我想使用 Firebase 回调从我的实时数据库中检索数据,将其存储在一个数组中,然后将该数据用于数据可视化。但是当我为数组记录控制台时,它返回空。我引用了this post 试图理解/修复我的错误,但我仍然遇到很多麻烦。

var genderData=[];
// Get counter values.
function getData(){
    var ref = firebase.database().ref().child('counters');

    return ref.once('value').then((snapshot) => {
        snapshot.forEach((element) => {
            genderData.push(element.val()['Male']);
        });
        return genderData;
    });
}

console.log(genderData);

我的控制台显示:

最终,我希望能够使用我的数组通过 Chart.js 库生成图表:

// Bar graph displaying the total number of students by gender.
var ctx = document.getElementById("myChart4").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Male", "Female", "Non-Binary", "Other", "Unspecified"],
        datasets: [{
            data: genderData,
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)',
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        title: {
            display: true,
            text: 'Total Students by Gender'
        },
        legend:{
            display: false
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});

我已经解决这个问题几个小时了,但没有解决方案。我想要的只是用我的数据库数据创建一个简单的数组,但是我遇到了很多麻烦。我真的希望有人可以帮助我找到一个优雅的解决方案。

编辑

一点我的数据库结构,以防万一:

【问题讨论】:

  • 如果您将值推送到数组,为什么还要返回它?

标签: javascript arrays firebase asynchronous firebase-realtime-database


【解决方案1】:

Firebase 异步加载数据。这意味着任何需要访问数据的代码都必须在 then() 回调中,或者必须使用自己的 then() 回调。

使用您当前对getData 的定义,您可以调用它并将数据用于:

getData().then((data) => {
  console.log("In callback");
  console.log(data);
  console.log(genderData);
})
console.log("Outside callback");
console.log(genderData);

如果你运行这段代码,你会看到:

外部回调

[]

内部回调

[项目1,项目2,...]

[项目1,项目2,...]

注意事项:

  1. Outside callback 代码在Inside callback 代码之前运行,这可能不是您所期望的。
  2. 回调之外的代码运行,数组仍然是空的。只有在回调中的代码运行后,数组才会包含数据。
  3. 在回调内部,genderDatadata 是相同的。这是因为您在回调中return genderData,然后将其冒泡到then() 方法。

您的最终解决方案是创建图表的代码(您需要数据的地方)应该是 inside then 回调之一,以便在数据已加载。例如:

getData().then((data) => {
   var myChart = new Chart(ctx, {
     type: 'bar',
     data: {
        labels: ["Male", "Female", "Non-Binary", "Other", "Unspecified"],
        datasets: [{
            data: data,
            ... 

【讨论】:

  • 这是有道理的。但是我想现在我遇到了一个不同的问题:当我按照您的建议记录数据时,我的所有值都是未定义的(并且值太多了——应该有 13 个时是 54)。这可能是什么原因造成的?我已经附上了我的数据库结构的屏幕截图,以防万一。
  • 我的猜测是您多次调用getData(),并且每次都将所有项目添加到genderData。但这只是一个猜测。请注意,这些都与 chart.js 库本身无关,因此我建议查看 how to create a minimal, complete, verifiable example 以减少问题的范围。
  • 是的,我相信这是forEach 循环。我删除了它并简单地做了genderData.push(snapshot.val()['Male']);,现在我的控制台似乎正在按预期记录(我希望)。这是截图:imgur.com/a/Dil6ojT
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 2017-05-26
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多