1

Apologies for the very beginner question.

I'm trying to use this answer to read in data in a JSON file into my javascript. I've pasted the code from the answer directly into the top of my javascript (changing pathToFile.json obviously). What I'm not sure about is what I'm supposed to do where the "do something with your data" comment is. I just want to have the parsed data object available to the rest of my code, but being extremely new to javascript I don't really understand how the callback function works. I can see the data from the JSON file logged in the console when I run it but every (no doubt dumb) thing I've tried to do to 'get it out' of the function hasn't worked -- I get a ReferenceError: data is not defined message when I try to refer to it later.

Here's the code from the other answer:

function fetchJSONFile(path, callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === 4) {
            if (httpRequest.status === 200) {
                var data = JSON.parse(httpRequest.responseText);
                if (callback) callback(data);
            }
        }
    };
    httpRequest.open('GET', path);
    httpRequest.send(); 
}

// this requests the file and executes a callback with the parsed result once
//   it is available
fetchJSONFile('pathToFile.json', function(data){
    // do something with your data
    console.log(data);
});
Community
  • 1
  • 1
aPaulT
  • 593
  • 3
  • 8
  • I've got this working now, by making all the rest of my code a function, and calling that function from inside the `fetchJSONFile` function, which I guess was obvious in retrospect. – aPaulT May 16 '15 at 12:04

1 Answers1

2

That's because data is defined as a local variable in the scope of onreadystatechange and the callback functions. Assuming you do not want to try jQuery or some other framework, you may try it like this to bind the data to a global variable:

var app = (function(){

    var json;

    function fetchJSONFile(path, callback) {
        var httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = function() {
            if (httpRequest.readyState === 4) {
                if (httpRequest.status === 200) {
                    var data = JSON.parse(httpRequest.responseText);
                    if (callback) callback(data);
                }
            }
        };
        httpRequest.open('GET', path);
        httpRequest.send(); 
    }

    // this requests the file and executes a callback with the parsed result once
    //   it is available
    fetchJSONFile('pathToFile.json', function(data){
        // do something with your data
        json = data;
    });

    return { getData : function()
    {
        if (json) return json;
        else return false;//or show some msg that 'data is not loaded yet'
    }};

})();

// you now have access to your data via:
app.getData(); // will either be false or contain the data 

Regarding your question about the callback function, it is a function that you pass to fetchJSONFile that will get called once the data is retrieved from the httpRequest. Since that is asynchronous you don't control when the callback function gets called - it will be called once the request completes with an OK status (given your current implementation). So everything under "do something with your data" is what will be executed once the data is retrieved and parsed (that is the body of your callback function).

chris
  • 1,787
  • 1
  • 13
  • 13
  • So do I then refer to `app.data` in the rest of the code? I still seem to be getting it as undefined if I try... – aPaulT May 16 '15 at 10:42
  • 1
    You can once it is defined. Remember that the callback function is called asynchronously. app.data will not be defined until the callback is called. Check my updated answer which may be more clear. You now have a global reference app.getData() which will either be your json or false (instead of giving you undefined). – chris May 16 '15 at 11:01
  • OK, so if I understand, the reading of the json is 'asynchronous', ie, it happens 'in the background' while the rest of the code is running. So when I try to use it later on I run into problems because it hasn't loaded yet (I get app.getData() returning false in this case). And if I knew more about this stuff I'd be able to make it not run until the json has safely loaded? – aPaulT May 16 '15 at 11:14
  • 1
    That is correct. Depending on your implementation, you can always check app.getData() and if not false, carry on doing whatever you want to do with the data. I think as you get more comfortable with JS you can start using frameworks, such as Angular, which have their own peculiar ways of binding data to models and updating the DOM/views when it's ready. As a next step, perhaps you may want to check out jQuery, which saves you boilerplate code in doing AJAX request and such. – chris May 16 '15 at 13:29