Overcoming difficulties with JSON data loading (or another mistake)

You’re loading D3 v4; in Observable you really want to use D3 v5, which replaces the callback-style API of d3-request with the promise-based API of d3-fetch. (See CHANGES for more.) Observable, and today’s JavaScript in general with async and await, have standardized on promises for asynchronous code.

So first, replace this:

d3 = require("https://d3js.org/d3.v4.min.js")

With this:

d3 = require("https://d3js.org/d3.v5.min.js")

(You might also use the non-minified d3.v5.js when developing for easier debugging.)

Then replace this callback:

d3.json("jsondata", function(error, root) {
  …
})

With either promise.then:

d3.json("jsondata").then(function(root) {
  …
})

Or await:

{
  const data = await d3.json("jsondata");
  …
}

And in Observable, if the value of a cell is a promise, then referencing that value from another cell will implicitly await the promise, so the best approach is to say:

data = d3.json("jsondata")

See Introduction to Promises for more on this topic.

But none of these examples will work yet :anger: , because per the d3-fetch README, the first argument to d3.json is a URL, not a name, and not a JSON object. The above cells are all looking for a file named “jsondata” relative to the notebook, and obviously that file does not exist. And similarly, when you say:

d3.json({"name": "flare", "children": […]})

It’ll trying to load a file named “[object Object]”… and yeah, that’s not going to work. :grin:

Per the Introduction to Data notebook, two currently-recommended approaches are to host your data on GitHub, say as a gist, or to inline the data directly in your notebook if it’s small. With the latter approach, that would simply be:

data = ({
  "name": "flare",
  "children": [
    …
  ]
})

Or, to load from GitHub, using one of my existing gists of the Flare dataset:

data = d3.json("https://gist.githubusercontent.com/mbostock/1093025/raw/b40b9fc5b53b40836ead8aa4b4a17d948b491126/flare.json")

We’ve even made a require-able version of this dataset for convenience:

data = require("@observablehq/flare")

You can browse our example datasets on GitHub.

5 Likes