简体   繁体   English

Chartjs / Javascript-我的函数未正确返回数组,但控制台记录正常

[英]Chartjs / Javascript - My function not returning array properly, but console logs okay

Currently using Angular JS and ChartJS to try and put a chart on my page. 当前使用Angular JS和ChartJS尝试在我的页面上放置一个图表。 The data is requested through a route in NodeJS and then the functions loop through the leads that are in the response and try to count how many were created on each day of the month. 通过NodeJS中的路由请求数据,然后函数遍历响应中的线索,并尝试计算每月的每一天创建了多少。

When I console log the leadsPerDay it returns an array with everything how I would expect it, but the chart doesn't seem to render the dots appropriately. 当我用控制台记录LeadsPerDay时,它将返回一个数组,其中包含我所期望的一切,但是图表似乎并未适当地渲染点。 They all fall on the bottom which tells me it's finding my array because if I take it out, no dots. 它们全部落在底部,这告诉我正在找到我的阵列,因为如果我将其取出,则不会有点。 If I manually put in the array, it renders properly. 如果我手动放入数组,它将正确呈现。

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: getDaysInMonth(currentMonth, currentYear),
    datasets: [{
      label: '# new leads created',
      data: getLeadsForMonth(currentMonth, currentYear),
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)'
      ],
      borderColor: [
        'rgba(255,99,132,1)'
      ],
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  },
  maintainAspectRatio: false
});

function getDaysInMonth(month, year) {
  var date = new Date(year, month, 1);
  var dates = [];
  while (date.getMonth() === month) {
    var currentDate = new Date(date).toISOString().replace(/T.*/, '').split('-').reverse().join('-');
    var catDate = currentDate.replace(/-2017/g, '').replace(/-/g, '/').split('/').reverse().join('/');;
    dates.push(catDate);
    date.setDate(date.getDate() + 1);
  }
  return dates;
}

function getLeadsForMonth(month, year) {

  // Create empty array to put leadCount in
  var leadsPerDay = new Array();

  /* Use $http.get to fetch contents*/
  $http.get('/pipedrive/getLeadsForMonth', function() {}).then(function successCallback(response) {

    // Loop through each lead and index them based on date
    var leads = response.data.data[0].deals;
    // Set date to first of the month
    var date = new Date(year, month, 1);
    // Define the month for the loop
    var currentMonth = date.getMonth();

    // Loop through the days in the month
    while (date.getMonth() === currentMonth) {
      // Save the date
      var currentDate = new Date(date).toISOString().replace(/T.*/, '');
      date.setDate(date.getDate() + 1);
      leadCount = 0;
      // Loop through each lead and search data for date
      for (i = 0; i < leads.length; i++) {
        if (leads[i].add_time.includes(currentDate)) {
          leadCount++
        }
      }
      leadsPerDay.push(leadCount);
    }
  }, function errorCallback(response) {
    console.log('There was a problem with your GET request.')
  });
  console.log(leadsPerDay);
  return leadsPerDay;
}

The problem here is that the chart is being rendered before the data is actually returned from your function, because you are making an asynchronous call to your endpoint. 这里的问题是图表是在实际从函数返回数据之前呈现的,因为您正在异步调用端点。

Here is the current flow. 这是电流。

1) You instantiate a new chart which then synchronously calls 2 functions to get the labels ( getDaysInMonth ) and data ( getLeadsForMonth ). 1)实例化一个新图表,然后同步调用2个函数以获取标签( getDaysInMonth )和数据( getLeadsForMonth )。

2) The label function returns no problem with your label data. 2)标签功能对您的标签数据没有任何问题。 The data function however then does an async call to an endpoint to acquire data. 但是,数据功能然后对端点进行异步调用以获取数据。 $http.get returns a Promise and when it is ready you are processing the result and building your data array. $http.get返回一个Promise,准备就绪后,您将处理结果并构建数据数组。 Unfortunately at this point, the initial call to getLeadsForMonth has already returned with an empty array. 不幸的是,此时,对getLeadsForMonth的初始调用已经返回了一个空数组。

The reason you are able to see your data using console.log is probably just a timing issue. 您能够使用console.log查看数据的原因可能只是时间问题。 By the time the browser executes that statement chances are the $http.get already returned (especially true if you are running this on locahost) and the data is now present in the array (however the chart is already rendered so it does not show it). 到浏览器执行该语句时,可能已经返回了$http.get (特别是如果在locahost上运行此命令,则为true),并且数据现在已存在于数组中(但是图表已经呈现,因此它不显示它) )。

Since you are asynchronously acquiring your data you have a couple of options. 由于您是异步获取数据,因此有两种选择。

1) Wait and create your chart after the data is acquired. 1)等待并在获取数据后创建图表。 You could do this by moving the chart creation code inside your $http.get callback. 您可以通过在$http.get回调中移动图表创建代码来完成此操作。 Something like this... 像这样

function getDaysInMonth(month, year) {
  var date = new Date(year, month, 1);
  var dates = [];
  while (date.getMonth() === month) {
    var currentDate = new Date(date).toISOString().replace(/T.*/, '').split('-').reverse().join('-');
    var catDate = currentDate.replace(/-2017/g, '').replace(/-/g, '/').split('/').reverse().join('/');;
    dates.push(catDate);
    date.setDate(date.getDate() + 1);
  }
  return dates;
};

function createChart(month, year) {
  // generate the labels
  var labels = getDaysInMonth(month, year),

  // Create empty array to put leadCount in
  var leadsPerDay = new Array();

  /* Use $http.get to fetch contents*/
  $http.get('/pipedrive/getLeadsForMonth', function() {}).then(function successCallback(response) {

    // Loop through each lead and index them based on date
    var leads = response.data.data[0].deals;
    // Set date to first of the month
    var date = new Date(year, month, 1);
    // Define the month for the loop
    var currentMonth = date.getMonth();

    // Loop through the days in the month
    while (date.getMonth() === currentMonth) {
      // Save the date
      var currentDate = new Date(date).toISOString().replace(/T.*/, '');
      date.setDate(date.getDate() + 1);
      leadCount = 0;
      // Loop through each lead and search data for date
      for (i = 0; i < leads.length; i++) {
        if (leads[i].add_time.includes(currentDate)) {
          leadCount++
        }
      }
      leadsPerDay.push(leadCount);
    }

    var ctx = document.getElementById("myChart");
    var myChart = new Chart(ctx, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          label: '# new leads created',
          data: leadsPerDay,
          backgroundColor: [
            'rgba(255, 99, 132, 0.2)'
          ],
          borderColor: [
            'rgba(255,99,132,1)'
          ],
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          yAxes: [{
            ticks: {
              beginAtZero: true
            }
          }]
        }
      },
      maintainAspectRatio: false
    });
  }, function errorCallback(response) {
    console.log('There was a problem with your GET request.')
  });
};

createChart(currentMonth, currentYear);

2) Create an empty chart and then use the .update() prototype method to re-render the chart when the data is acquired. 2)创建一个空图表,然后在获取数据时使用.update()原型方法重新呈现该图表。 Something like this... 像这样

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: getDaysInMonth(currentMonth, currentYear),
    datasets: [{
      label: '# new leads created',
      data: [],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)'
      ],
      borderColor: [
        'rgba(255,99,132,1)'
      ],
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  },
  maintainAspectRatio: false
});

getLeadsForMonthAndUpdateChart(myChart, currentMonth, currentYear);

function getLeadsForMonthAndUpdateChart(chart, month, year) {
  // Create empty array to put leadCount in
  var leadsPerDay = new Array();

  /* Use $http.get to fetch contents*/
  $http.get('/pipedrive/getLeadsForMonth', function() {}).then(function successCallback(response) {

    // Loop through each lead and index them based on date
    var leads = response.data.data[0].deals;
    // Set date to first of the month
    var date = new Date(year, month, 1);
    // Define the month for the loop
    var currentMonth = date.getMonth();

    // Loop through the days in the month
    while (date.getMonth() === currentMonth) {
      // Save the date
      var currentDate = new Date(date).toISOString().replace(/T.*/, '');
      date.setDate(date.getDate() + 1);
      leadCount = 0;
      // Loop through each lead and search data for date
      for (i = 0; i < leads.length; i++) {
        if (leads[i].add_time.includes(currentDate)) {
          leadCount++
        }
      }
      leadsPerDay.push(leadCount);
    }

    // add the data to the chart and re-render
    chart.data.datasets[0].data = leadsPerDay;
    chart.update();
  }, function errorCallback(response) {
    console.log('There was a problem with your GET request.')
  });
};

Here is a codepen example that demonstrates the second option (updating the chart with new data) for you to look at as well. 这是一个Codepen示例 ,还演示了第二个选项(用新数据更新图表)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM