2

I am trying to get some data from url to work with in d3.js. I can't seam to get the data using d3.json(url, callback). While it works fine when I use (ES8) async await function.

Can someone help me understand why? What am I doing wrong? Thanks!

d3.json() example:

d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json", json => {
  
     const data = json.data; // array of dates and values
     const lowestVal = d3.min(data, d => d[1]);
     const highestVal = d3.max(data, d => d[1]);
     
     console.log(lowestVal);
     console.log(highestVal);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Async await example:

(async function() {
  try {
    const response = await fetch("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json");
    if (response.ok) {
      const jsonResponse = await response.json();
      
      const data = jsonResponse.data; // array of dates and values
      const lowestVal = d3.min(data, d => d[1]);
      const highestVal = d3.max(data, d => d[1]);
      
      console.log(lowestVal);
      console.log(highestVal);
    }
  } catch(error) {
    console.log(error);
  }
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

I understand there should be some CORS issue here also. But I am working on CodePen for the moment. So CORS is not a problem here.

Many thanks for any insights.

TVBZ
  • 564
  • 1
  • 4
  • 15

1 Answers1

2

According to the documentation, d3.json returns a promise, like fetch does, rather than accepting a callback. (Edit: Apparently in v4 it accepted a callback — that explains it.) If you use that promise, it works.

You can either use the promise via async/await as you did with fetch, or by using then and (since you're not returning the chain to anyone else who would handle it) catch.

async/await:

(async function() {
  try {
    const jsonResponse = await d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json");

    const data = jsonResponse.data; // array of dates and values
    const lowestVal = d3.min(data, d => d[1]);
    const highestVal = d3.max(data, d => d[1]);

    console.log(lowestVal);
    console.log(highestVal);
  } catch(error) {
    console.log(error);
  }
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

then/catch:

d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json")
.then(json => {
  
     const data = json.data; // array of dates and values
     const lowestVal = d3.min(data, d => d[1]);
     const highestVal = d3.max(data, d => d[1]);
     
     console.log(lowestVal);
     console.log(highestVal);
})
.catch(error => {
    console.error(error);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Thanks! Indeed in d3.js v5 there is no longer a callback function because it returns a promise. I was looking at an example in d3 v4 while working in v5 :) – TVBZ Jun 11 '19 at 11:09