1

I'm using jquery.csv.min.js to create an array based on a csv. This part works fine. However, when I try and parse that 2d array into sessionStorage items, I'm getting the dreaded "Uncaught TypeError: Cannot read property '0' of undefined". Here's what I have so far:

var stationData;
var station = "";

// Gather data from CSVs

$.ajax({
    type: "GET",
    url: "document.csv",
    dataType: "text",
    success: function(response){
        stationData = $.csv.toArrays(response);
        console.log(stationData);  // This works and confirms the array in the console
        console.log("Station Variables Success!");
    }
});

// Parse array into sessionStorage items

$(document).ready(function() {  
    setTimeout(() => {
        station = getUrlParameter('stn');
        var v;
        var varLen = stationData[0].length;
        for(v = 0; v < varLen; v++) {
            sessionStorage.setItem(stationData[0][v], stationData[station][v]);  // Line producing error
            console.log("Setting sessionStorage:" + stationData[0][v] + " to \"" + stationData[station][v] + "\"");
    }}, 2000);
});

When I run this on my local XAMPP Apache server, I was getting the same TypeError until I included the setTimeout() to space it out a bit figuring it was trying to set the storage items before the array could finish loading and it worked. Just a 10ms timeout is enough to run it on my local server, which is why it's there. However, when I try and upload this to our live server, the TypeError comes back. I've tried increasing the timeout in increments upto 10000ms but it's still happening. I've googled around with no luck, so I'm hoping someone here might be able to share some insight!

Mike Z
  • 13
  • 2

1 Answers1

1

It's throwing TypeError because you are trying to read the value of an asynchronous operation before its returned by the server.

Increasing the timeout is not the option.

You just need to slightly refactor your code like this -

$(document).ready(function() {
    function fetchCSVFromServer(successCb, errorCb) {
        return $.ajax({
            type: "GET",
            url: "document.csv",
            dataType: "text"
        })
        .done(successCb)
        .fail(errorCb);
    }

    var successCb = function(response){
        // Parse array into sessionStorage items
        var stationData = $.csv.toArrays(response);
        console.log(stationData);  // This works and confirms the array in the console
        console.log("Station Variables Success!");

        setTimeout(() => {
            var station = getUrlParameter('stn');
            var varLen = stationData[0].length;
            for(let v = 0; v < varLen; v++) {
                sessionStorage.setItem(stationData[0][v], stationData[station][v]);  // Line producing error
                console.log("Setting sessionStorage:" + stationData[0][v] + " to \"" + stationData[station][v] + "\"");
            }
            
        }, 2000);
    };
    
    var errorCb = function(jqXHR, textStatus, errorThrown) {
        console.error(jqXHR);
    };

    fetchCSVFromServer(successCb, errorCb); 
});

This code has 2 parts to it, first making the XHR using the $.ajax in the fetchCSVFromServer function and the second synchronizing the code flow which follows the asynchronous XHR call which is written in the successCb callback.

The trick is to synchronize the callback to run only after the server has sent its response in the .done callback.

This is a well known and a solved problem, for more details refer this question.

Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53
  • Thanks for the quick response! I tried pasting it in as written and I'm still running into the same error on the same line. I'm still pretty new to all this and figured there was a detailed explanation somewhere, but wasn't sure where to look. I'll read through that other question and hopefully it will help shed some more light on it. Much appreciated! – Mike Z May 06 '21 at 17:55