javascriptd3.jsdagre-d3

setting d3 graph from inside of an anonymous function


I am trying to read a JSON file which looks like:

[ {
"parent" : "cmeta_transform",
"path" : "hcat://sample/dt=yyyyMMddHH",
"child" : "lite_video_hourly"
} ]

Then, I am iterating over the contents and setting the Node and Edges from inside the data.forEach function call (code below)

But, it seems like the variable g is not getting set when I iterate over it. If I do it outside the anonymous function, it works. What am I missing?

<script id="js">
// Create a new directed graph
var g = new dagreD3.graphlib.Graph().setGraph({});

d3.json("expectedOutput.json", function(data) {
    data.forEach(function (job) {
        console.log(job); // I do see job values correctly.
        g.setNode(job.child, { label: job.child });
        g.setEdge(job.parent,     job.child,     { label: job.path });
    });
});

console.log(g); // g doesn't have the nodes & edges values set above

// if I do this
g.setNode(job.child, { label: job.child });
g.setEdge(job.parent,     job.child,     { label: job.path });
console.log(g); // I see g is set properly
</script>

Solution

  • This happens because requesting the JSON via AJAX is an asynchronous operation so the console.log is executed before what's inside the anonymous function.

    You may want to look at promises in JavaScript or at least put your code inside that function so the result of the request is available to your code. At the simplest level this should work:

    function draw(data) {
      var g = new dagreD3.graphlib.Graph().setGraph({});
      data.forEach(function (job) {
          console.log(job); // I do see job values correctly.
          g.setNode(job.child, { label: job.child });
          g.setEdge(job.parent,     job.child,     { label: job.path });
      });
      // carry on doing what you need in here...
    }
    
    d3.json("expectedOutput.json", draw);