Chapter 03Using D3-fetch

The d3-fetch module provides various convenience methods that are built on top of the Fetch data transfer standard.

<script src="https://d3js.org/d3-fetch.v1.min.js"></script>

The d3-fetch convenience methods are shown below.

Below are examples on how to use all but the last 2 methods.

When calling the dsv, csv, tsv, json, xml, html, and text download functions, you’ll find a call to then chained to the download function call as shown below. The code in the function passed to then is executed after the file is downloaded and the data within the file is ready to be used.

d3.dsv(delimiter, fileName)
    .then(function(data) {
    // download has completed - do something with data
});

// may be executed before the code passed to then() is executed!

This pattern is necessary because the browser does not wait for the data to be downloaded.  Instead, the browser will request the download and continue with the rest of the code in the JavaScript file.  When the download has finished, the browser will jump to the code within the call to then and execute it.

To be clear, any code that relies on the data in the downloaded file must be executed after the file has been downloaded and is usually included in the function passed to then. Second, any code that is written after the then call, may be executed before the file has been downloaded and before the function passed to then is executed.

In the examples below we use the d3-fetch functions to retrieve the contents of various data files that we have on our server. All of the files store similar information, just in different formats. In each examples, we pass a function to then that converts the data that is returned by the helper functions to an array of objects, each having the properties letter, number, and color (if it is not already in that format).  We then pass the id of an svg element and the array of objects to drawText (shown below) which writes the text contained in the objects of the array to the svg element.

function drawText(id, data) {
    d3.select(id)
      .selectAll("text")
      .data(data)
      .enter()
      .append("text")
      .attr("y", (d,i) => i * 20 + 20)
      .attr("x", 10)
      .text((d) => d.letter + " " + d.number + " " + d.color);
 }
 

d3.dsv

The code fragment below fetches a file named sample.dsv which contains the following text.

letter|number|color
A|1|red
B|2|blue

Here is the code to read the dsv file.

<script>
  d3.dsv("|", "samples/sample.dsv")
      .then(function(data) {

          drawText("#dsvDemo", data);
       });
</script>

<svg id="dsvDemo" class="lightblue" width="80" height="50"></svg>

d3.csv

The code fragment below fetches a file named sample.csv which contains the following text.

letter,number,color
A,1,red
B,2,blue

Here is the code to read the csv file.

<script>
  d3.csv("samples/sample.csv")
      .then(function(data) {

          drawText("#csvDemo", data);
       });
</script>

<svg id="csvDemo" class="lightblue" width="80" height="50"></svg>

d3.tsv

The code fragment below fetches a file named sample.tsv which contains the following text.

letter  number  color
A   1   red
B   2   blue

Here is the code to read the tsv file.

<script>
  d3.tsv("samples/sample.tsv")
      .then(function(data) {

          drawText("#tsvDemo", data);
       });
</script>

<svg id="tsvDemo" class="lightblue" width="80" height="50"></svg>

d3.json

The code fragment below fetches a file named sample.json which contains the following text.

{
  "0":{
    "letter": "A",
    "number": 1,
    "color": "red"
    },
  "1": {
    "letter": "B",
    "number": 2,
    "color": "blue"
    }
}

Here is the code to read the json file.

<script>
  d3.json("samples/sample.json")
      .then(function(data) {

          // data is an object, convert to array.
          data = [data[0], data[1]];

          drawText("#jsonDemo", data);
       });
</script>

<svg id="jsonDemo" class="lightblue" width="80" height="50"></svg>

d3.xml

The code fragment below fetches a file named sample.xml which contains the following text.

<?xml version="1.0" encoding="UTF-8" ?>
<data>
  <item>
      <letter>A</letter>
      <number>1</number>
      <color>red</color>
  </item>
  <item>
      <letter>B</letter>
      <number>2</number>
      <color>blue</color>
  </item>
</data>

Here is the code to read the xml file.

<script>
  d3.xml("samples/sample.xml")
      .then(function(data) {

          // data is an XML document, parse document
          data = [].map.call(data.querySelectorAll("item"), function(item) {

              return {
                  letter: item.querySelector("letter").textContent,
                  number: item.querySelector("number").textContent,
                  color: item.querySelector("color").textContent
              };
          });

          drawText("#xmlDemo", data);

       });
</script>

<svg id="xmlDemo" class="lightblue" width="80" height="50"></svg>

d3.html

The code fragment below fetches a file named sample.html which contains the following text.

<html>
  <body>
    <p>A 1 red</p>
    <p>B 2 blue</p>
  </body>
</html>

Here is the code to read the html file.

<script>
  d3.html("samples/sample.html")
      .then(function(data) {

          // data is an HTML document, parse document
          data = [].map.call(data.querySelectorAll("p"), function(node) {

              let tokens = node.textContent.split(" ");

              return {
                  letter: tokens[0],
                  number: tokens[1],
                  color: tokens[2]
              };
          });

          drawText("#htmlDemo", data);
       });
</script>

<svg id="htmlDemo" class="lightblue" width="80" height="50"></svg>

##d3.text

The code fragment below fetches a file named sample.txt which contains the following text.

A 1 red
B 2 blue

Here is the code to read the text file.

<script>
  d3.text("samples/sample.txt")
      .then(function(data) {

          // data is a string
          data = data.split("\n");

          data = data.map((str) => {
              let tokens = str.split(" ");

              return {
                  letter: tokens[0],
                  number: tokens[1],
                  color: tokens[2]
              };
          });

          drawText("#textDemo", data);
       });
</script>

<svg id="textDemo" class="lightblue" width="80" height="50"></svg>

d3.svg

The code fragment below fetches a file named sample.svg which contains the following text.

<svg id="svgDemo" xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="64" height="64" >
    <rect width="100%" height="100%" fill="green" />
    <circle cx="40" cy="40" r="40" fill="blue" />
</svg>

Here is the code to read the svg file.

<script>
  d3.svg("samples/sample.svg")
      .then(function(data) {

         var oldChild = document.getElementById("svgDemo");
         document.getElementById("svgDemo").parentNode.replaceChild(data.documentElement, oldChild);
       });
</script>

<svg id="svgDemo" class="lightblue" width="80" height="50"></svg>

d3.image

The code fragment below fetches a file named sample.png which contains a png that was created by exporting the above svg to a file with the png format.

Here is the code to read the png file.

<script>
  d3.image("samples/sample.png")
      .then(function(data) {

         let canvas = document.getElementById("imageDemo");
         let ctx = canvas.getContext('2d');
         ctx.drawImage(data, 0,0);
       });
</script>

<canvas id="imageDemo" width="64px" height="64px"></canvas>