0

I'm running a HTML file which comes up with an error "Uncaught TypeError: Cannot read property '0' of undefined"

My javascript code is

function loadHeatMap(){
    xhr=new XMLHttpRequest();
    xhr.open('GET','/LinkedIn/heatMap.json',true);
    xhr.onreadystatechange=function(){
        if(xhr.readyState===4&&xhr.status===200){
            heatData=JSON.parse(xhr.responseText).data;
            console.log("Heat Map JSON data");
        }};
    xhr.send(null);
}

loadHeatMap();
var name = heatData.set[0].name;

The JSON is structured like this

{"data":[{"set":[{"name":"Joe","sold":"100","target":"200"},{"name":"Tim","sold":"200","target":"100"}]}]}

The error occurs at the line 'heatData.set[0].name, saying that 0 is undefined.

Can someone please let me know what I'm doing wrong.

karthikr
  • 87,486
  • 24
  • 182
  • 182
John Henry
  • 165
  • 4
  • 14
  • 3
    You're trying to use an asynchronous Ajax call as if it was synchronous. Any processing that needs to be done on the returned data should be done in your readystatechange callback (or in functions called from there). You can see the async sequence of execution if you add some more `console.log()` statements after the call to the `loadHeatMap()` function. (And as an aside: one doesn't iterate over JSON, one parses JSON and iterates over the resulting object.) – nnnnnn May 23 '13 at 21:16
  • `heatData['name']` in addition to @nnnnnn – km6zla May 23 '13 at 21:20
  • You should also ensure that `heatData` contains something before accessing it; if the ajax call ever fails, everything fails. – Frederik.L May 23 '13 at 21:21
  • P.S. The fix for this is _not_ to change the Ajax to be synchronous. That provides a poor experience for the user. – nnnnnn May 23 '13 at 21:22
  • I did try using a callback function, but as I can see from David's helpful snippet, I need to brush up on my callbacks – John Henry May 23 '13 at 21:41

3 Answers3

2

XMLHttpRequests are asyncronous, meaning that the request will not have assigned heatData with anything at the time where you assign data to your variable name.

You must make sure you do any processing of your returned data after the request has finished. An easy way to achieve this would be to just send in a callback to the function.

function loadHeatMap(callback) {
    xhr=new XMLHttpRequest();
    xhr.open('GET','/LinkedIn/heatMap.json',true);
    xhr.onreadystatechange=function(){
        if(xhr.readyState===4&&xhr.status===200){
            heatData=JSON.parse(xhr.responseText).data;
            // Run your callback with the data
            callback instanceof Function && callback(heatData);
        }};
    xhr.send(null);
}

loadHeatMap(function(heatData) {
    // Do all your processing with heatData here
});
David Barker
  • 13,767
  • 3
  • 40
  • 73
0

You'll need to listen for the onReadyStateChange event from the xhr object and wait until it's '4'. This means the data is loaded and respons is ready. Then you can check the heatData.set[0].name. Right now you are trying to access it before it has had a chance to load.

earl3s
  • 2,195
  • 1
  • 20
  • 23
0
heatData=JSON.parse(xhr.responseText).data;

this should return this array

[{"set":[{"name":"Joe","sold":"100","target":"200"},{"name":"Tim","sold":"200","target":"100"}]}]

so I think you have to do this:

heatData[0].set[0].name

hope it helps

BeNdErR
  • 15,879
  • 16
  • 63
  • 97