Cmagelssen
Cmagelssen

Reputation: 660

'data.forEach is not a function' when loading csv in d3.js

I am building a simple feedback system for a study. I have just started to learn JS and D3.js, but decided to build some very simple plot in D3.js. However, I get the following error message and I don't understand how I can fix it?

(index):36 Uncaught (in promise) TypeError: data.forEach is not a function

What I want to do with this script is to take a single line in a .csv and put the number on the screen. This my code


const inter = setInterval(function() {
                updateData();
        }, 5000); 

// ** PLOG
function updateData() {

    // Get the data again
    d3.csv("lagplot.csv", function(error, data) {
        data.forEach(function(d) {
            d.finish = +d.FINISH;
            d.bib = +d.BIB;
        });
        

    // PLOT TEXT
        d3.select("text")   
            .data(data)
            .enter()
            .append("text")
                .attr("fill", "teal")
                .text(function(d) { return d.finish; })
            });
        }

And this how the csv file looks

    Unnamed: 0  RANK  STA  RUN  BIB           NAME  INTER 1  INTER 1.1  INTER 1.2    INTER 2   INTER 2.1  INTER 2.2  FINISH     FINISH.1  FINISH.2   COURSE
33          33    34    9    4    2  OFTEBRO Einar     4.85       3.72         33  10.145.29  +8.10+4.38     3232.0  14.053  +11.28+3.18      32.0  LØYPE 3

Upvotes: 1

Views: 2314

Answers (2)

gherka
gherka

Reputation: 1446

Your code is fine. What causes the error is the difference in d3 versions. Most of the tutorials on the web were written for v3 or v4 where you loaded the csvs in the way you've written. If you try to do this with v5 or later, you'll get the error. Check your <script> tag for d3 and either change it to v4 or change your code along the lines that Klaycon suggested in his answer.

Upvotes: 1

Klaycon
Klaycon

Reputation: 11080

According to the docs, the function you're passing to d3.csv() is not a callback, but a row conversion function - what you're passed is not (error, data) but just d (the row being converted). You should skip the data.forEach and use the row conversion function for that, and put the rest of the code in the .then() callback.

// Get the data again
d3.csv("lagplot.csv", function(d) {
    d.finish = +d.FINISH;
    d.bib = +d.BIB;
    return d;
}).then(function(data) {
    // PLOT TEXT
    d3.select("text")   
        .data(data)
        .enter()
        .append("text")
        .attr("fill", "teal")
        .text(function(d) { return d.finish; })
});

Upvotes: 6

Related Questions