1

I've been trying to learn the basics of d3. I've run into some difficulty getting data from an external source. I've had functioning charts before where the data is put in directly as an JSON object or array, but I'm trying to work with a CSV right now. I'm trying to push the data into an array of objects, and while it seems to work partially, something strange is going on with the array that I'm unable to access the information inside it:

var testArray = [
   {name: "John",
   height: "Six Feet"},
   {name: "Karl",
   height: "Seven Feet"}
]

console.log(testArray);
console.log(testArray[0].name)

var dataset = [];

d3.csv("../scripts/books.csv", function(data) {

   dataset.push( {
       title: data.Title,
       author: data.Author
   });

});

console.log(dataset);
console.log(dataset[0].title);

testArray is just used as example. When I log testArray[0].name it correctly returns "John" - but when I try the same format on dataset, it says "Cannot read property 'title' of undefined." I've tried with pure bracket notation and pushing the data in other formats, but nothing seems to work.

console results from above code

Some of the d3 guides suggest just doing everything you need to create your chart within the callback loop, but the way I learned and the way many online classes teach is to have the data separated out and build your own functions and loops to create the chart. I'm having difficulty reconciling these things. I do NOT want to build everything into the callback function, if at all possible.

mbateman
  • 23
  • 4
  • Because d3.csv is asynchronous, the order of your code blocks doesn't matter. `dataset` will be empty when you log to console because the csv is still loading, while the rest of the code continues to execute. You can call a function to draw the chart from the call back, that way you can split it out into distinct blocks of code: `d3.csv("...", function(data) { /* manipulate data */ drawChart(data); });` – Andrew Reid May 28 '20 at 15:43
  • I know you can manipulate and draw the chart within the function, my question specifically asked if there is a way to get the data outside the call back. Also, you can see in the image that dataset is not empty when logged to console, it lists all the books, but when I try to access a specific object and property, it fails. – mbateman May 28 '20 at 15:46
  • Try logging `dataset.length` only to see if there is any values in `dataset`, you can get the data outside the callback by passing it directly to the draw function as suggested. If you can't log dataset[0].title without an error that says can't read property title of undefined, then dataset[0] is undefined, no matter what logging the full dataset suggests. – Andrew Reid May 28 '20 at 15:48
  • logging `dataset.length` returns "0" and when I try to pass it in, so it is still undefined, thank you for that clarification. Trying to pass `dataset` into an external `drawChart()` function I have still runs into the undefined problem. – mbateman May 28 '20 at 15:56
  • 1
    If `drawChart(dataset)` when called in the callback also results in undefined issues, you likely have some other issue. To clarify, I'm suggesting a pattern like in this [answer](https://stackoverflow.com/a/17294710/7106086)'s code block (not the pattern offered in the first paragraph). Also, this non-d3 specific [question](https://stackoverflow.com/q/14220321/7106086), which probably is overkill, might offer you some methods in addressing the issue. – Andrew Reid May 28 '20 at 16:04
  • As for why console.log shows the full array - it has thrown me off many times - console.log has some odd behavior with objects, including arrays, as seen [here](https://medium.com/@tomsu/devtools-tips-day-5-the-curious-case-of-console-log-36bc7e27a97f) (not sure if that's the best reference but it's succinct). – Andrew Reid May 28 '20 at 16:23
  • Does this answer your question? [Convert d3.csv to promise?](https://stackoverflow.com/questions/48411829/convert-d3-csv-to-promise) async / await should do the trick. – Mehdi May 28 '20 at 17:35

0 Answers0