Switching from localhost to nodejs and express

I’m trying to learn more about p5.js by following the working with data tutorials

The code for both the
fetch csv exercise(https://github.com/CodingTrain/Intro-to-Data-APIs-JS/tree/source/module1/02_fetch_csv_exercise_p5) and
fetch_csv_exercise_multiple (https://github.com/CodingTrain/Intro-to-Data-APIs-JS/tree/source/module1/02_fetch_csv_exercise_multiple)
seems to work well with the locally hosted version via Python -m http-server (on my windows 10 machine)

However I set up a raspi on my local network (which I also use port forwarding to develop on) and I set up Node.js(11.9.0) with express(6.11.3) and now only the
fetch csv exercise example displays.
While the fetch_csv_exercise_multiple example does not load at all on the page. It just stays blank.

I went through the CodingTrain/website/tree/master/Node/sockets tutorial and I basically had it set up the same way so I’m somewhat at a loss as to what is causing the difference in behavior.

Big picture:
Eventually I would like to host a local site where I can display charts of data about my house (temps, electric usage…etc) and other more fun for the sake of learning (draw a certain shape to move to the next page?) Eventually interface this with some server side code, hot glue on some wings and see if it flies.

I thought at first p5.js wasn’t loading correctly from the cdn so I switched to a local file but that still didn’t help

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js"></script>
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
<script language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.dom.min.js"></script>

vs
<script language="javascript" src="../libraries/p5.js"></script>

I then thought perhaps express couldn’t handle the async/await as a express.static page but I believe in the node sockets tutorial Daniel Shiffman and other websites don’t mention that should be a problem.

Here is my node app.js

const express = require('express')
const app = express()
const port = 8080

app.use(express.static('public'))

var server = app.listen(port, ()=> console.log('express app listening on port ${port}!'))

Here is the first example that works in both environments.

let table;

function preload(){
                table = loadTable('KentJobHist.csv', 'csv', 'header');
                console.log(table);
}

function setup() {
                createCanvas(600,400);
                background(0);
                stroke(255);
                noFill();
                beginShape();
                for (var i = 0; i < table.getRowCount(); i++){
                                        let row = table.getRow(i);
                                        let salary = row.getNum('Annual Salary');
                                        let x = map(i, 0, table.getRowCount() - 1, 0, width);
                                        let y = map(salary, 0, 100000, height, 0);
                                        vertex(x,y);
                                }
                endShape();
}

Here is the second example that is not working

<script>

        async function setup(){
        const ctx = document.getElementById('chart').getContext('2d');
        const dataSalary = await getData();
        const myChart = new Chart(ctx, {
                type: 'line',
                data: {
                        labels: dataSalary.years,
                        datasets: [{
                                label: 'Salary',
                                data: dataSalary.amount,
                                fill: false,
                                backgroundColor: 'rgba(255, 99, 132, 0.5)',
                                borderColor: 'rgba(255, 99, 132, 1)',
                                borderWidth: 1
                        }]
                },
                options: {
                }
        });
        }


        async function getData(){
                const response = await fetch('KentJobHist.csv');
                const data = await response.text();
                const years = [];
                const amount = [];
                const rows = data.split('\n').slice(1);
                        rows.forEach(row => {
                                const cols = row.split(',');
                                console.log(cols);
                                const changedate = cols[17].split(" ");
                                console.log(changedate);
                                years.push(cols[16]+ ' '+ changedate[0]);
                                amount.push(parseFloat(cols[18]));
                        });
                return {years, amount};
                }
        </script>
1 Like

i use the
index.html from
https://github.com/CodingTrain/Intro-to-Data-APIs-JS/blob/source/module1/02_fetch_csv_exercise_multiple/index.html ,
and a dummy csv file and see


i am sure that dummy file was read and used, the inspect console was not very helpful
update with the original data see:


RPI setup details here


i had a hard time to get your above script tested,
and after it run not have your data file… anyhow
test2.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Coding Train: Data and APIs Project 2</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
  </head>
  <body>
    <h1>script code https://discourse.processing.org/t/switching-from-localhost-to-nodejs-and-express/14377</h1>
    <canvas id="chart" width="400" height="200"></canvas>


<script>
        window.addEventListener('load',setup);
        async function setup(){
        const ctx = document.getElementById('chart').getContext('2d');
                                console.log("start getData");
        const dataSalary = await getData();
        const myChart = new Chart(ctx, {
                type: 'line',
                data: {
                        labels: dataSalary.years,
                        datasets: [{
                                label: 'Salary',
                                data: dataSalary.amount,
                                fill: false,
                                backgroundColor: 'rgba(255, 99, 132, 0.5)',
                                borderColor: 'rgba(255, 99, 132, 1)',
                                borderWidth: 1
                        }]
                },
                options: {
                }
        });
        }


        async function getData(){
                                console.log("read assets/test.csv");
                const response = await fetch('assets/test.csv');
                //const response = await fetch('KentJobHist.csv');
                const data = await response.text();
                const years = [];
                const amount = [];
                const rows = data.split('\n').slice(1);
                        rows.forEach(row => {
                                const cols = row.split(',');
                                console.log(cols);
                                //const changedate = cols[17].split(" ");
                                //console.log(changedate);
                                //years.push(cols[16]+ ' '+ changedate[0]);
                                //amount.push(parseFloat(cols[18]));
                        });
                return {years, amount};
                }
        </script>







  </body>
</html> 

produce


1 Like

Thank you for the help. I believe I put a bandaid on the problem at least.
I was getting an error that I could not split on an empty line after all the lines of the csv had been processed.
I believe this stems from windows and linux treating csv and txt files (and pdf) slightly differently. (I know this is somewhat hand-wavey and that is because I’m not sure of the details on how.)

Anyhoo, I believe the Rpi thought there was an empty row at the end of the file. I put a check in the foreach row section to see if it’s length was >0 and put the splits in that block.

                rows.forEach(row => {
                        if (row.length>0){
                                const cols = row.split(',');
                                console.log(cols);
                                const changedate = cols[17].split(" ");
                                console.log(changedate);
                                years.push(cols[16]+ ' '+ changedate[0]);
                                amount.push(parseFloat(cols[18]));
                }});

And this seems to get rid of the error and let the rest of the page load successfully.

If I wasn’t successful this time I would have scrubbed my salary data out of my file and posted that as well and maybe you would have had the same error.

Is there a better way to not get an empty row at the end of a file. I checked and it didn’t seem there was a /n at the end of the last line in my csv.

2 Likes

good, same would be better also for the columns,

not ask for data you not know they exist

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Coding Train: Data and APIs Project 2</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
  </head>
  <body>
    <h1>script code https://discourse.processing.org/t/switching-from-localhost-to-nodejs-and-express/14377</h1>
    <canvas id="chart" width="400" height="200"></canvas>


    <script>
        window.addEventListener('load',setup);                // add kll

        async function setup(){
        const ctx = document.getElementById('chart').getContext('2d');
        console.log("start getData");                        // add kll
        const dataSalary = await getData();
        const myChart = new Chart(ctx, {
                type: 'line',
                data: {
                        labels: dataSalary.years,
                        datasets: [{
                                label: 'Salary',
                                data: dataSalary.amount,
                                fill: false,
                                backgroundColor: 'rgba(255, 99, 132, 0.5)',
                                borderColor: 'rgba(255, 99, 132, 1)',
                                borderWidth: 1
                        }]
                },
                options: {
                }
        });
        }


        async function getData(){
                console.log("read assets/test.csv");               // add kll
                const response = await fetch('assets/test.csv');   // mod kll
                //const response = await fetch('KentJobHist.csv');
                const data = await response.text();
                const years = [];
                const amount = [];
                const rows = data.split('\n').slice(1);                              // ?? kill header?
                console.log(" found rows: "+rows.length);                  // add kll
                        rows.forEach(row => {
                            if ( row.length > 0 ) {                        // Kent
                                const cols = row.split(',');
                                console.log(" found cols: "+cols.length);  // add kll
                                if ( cols.length >= 19 ) {                 // add kll
                                   const changedate = cols[17].split(" ");
                                   console.log(changedate);
                                   years.push(cols[16]+ ' '+ changedate[0]);
                                   amount.push(parseFloat(cols[18]));
                                }
                            }
                        });
                return {years, amount};
                }
        </script>

  </body>
</html> 

Hmm. Honestly, I think that is a good solution – to assume that lines could be empty and handle them correctly. Among other things, ending linebreak is POSIX standard, so if you get your rows by splitting on linebreaks then this should happen with valid files. That meanss you either handle it while looping, or you handle it before looping (for example, just checking the last row and trimming it if empty).

1 Like