Question

An object that uses d3.csv() to set it's data property for use elsewhere. The downside is none of this works because d3.csv() is async. How can I solve this?

function BarChart(csvPath) {
  this.data = d3.csv('csvPath', function(csvData) {
    return csvData;
  });

  this.drawGraph = function() {
    // some code to draw a graph using this.data
  } 

  this.drawDataTable = function() {
    // some code to draw a graph using this.data
  }

  ... a bunch more code for using the data
}

Some code executed on page load and an event handler.

var barChart = new BarChart('my_data.csv');
barChart.drawGraph();

$('button.viewPreview').click(function(){
  barChart.drawDataTable();
});
Was it helpful?

Solution

Make BarChart accept a ready callback (a function)

function BarChart(csvPath, ready) {
  var _this = this;
  d3.csv('csvPath', function(csvData) {
    _this.data = csvData
    ready()// invoke the callback
  });

  this.drawGraph = function() {
    // some code to draw a graph using this.data
  } 

  this.drawDataTable = function() {
    // some code to draw a graph using this.data
  }

  ... a bunch more code for using the data
}

When you instantiate barchart, supply the ready callback:

var barChart = new BarChart('my_data.csv', function() {
  barChart.drawGraph();

  $('button.viewPreview').fadeIn();// unhide the button only when ready
});


$('button.viewPreview').click(function(){
  barChart.drawDataTable();
});

But, IMO, it's not a great idea to make a class that's responsible for drawing a barchart also responsible for loading its data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top