Search code examples
javascriptcallbackxmlhttprequest

access to a variable "outside" of a callback function in javascript


loadJSON(path, callback) {
    console.log("path: " + path); 
    var xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
    xobj.open('GET', path, true);
    xobj.onreadystatechange = function () {
          if (xobj.readyState == 4 && xobj.status == "200") {
            callback(xobj.responseText);
          }
    };
    xobj.send(null);  
 }

Above is a function to access a json file locally. Then from `foobar()' parse the data retrieved. However from "outside" of call back function, the variable "json" cannot be accessed. I had searched similar SO questions and async concepts but still was not able to figure a way to resolve it.

function foobar() { 
    var json;
    loadJSON("data.json", function(response) {
        json = JSON.parse(response);
        console.log(json[0].name); // Successfully shows the result
    });
    console.log(json[0].name); // TypeError: json is undefined
}

Is there a way to access the variable "outside" of the callback?


Solution

  • It's because it's set in Asynchronous mode.

    console.log(json[0].name); // TypeError: json is undefined
    

    This code is executed before json is filled. Therefore when you try to access it, it might be still empty. The third argument in this line defines it as Async:

    xobj.open('GET', path, true);
    

    You could try to put

    xobj.open('GET', path, false);
    

    But it isn't asynchronous anymore and the user will have to wait for the request to end, so it's probably better to make sure to use the 'json' var when the callback method has ben called and not before. Keeping the asynchrnous mode on. For this you'll need to restructure your code.

    The link posted by Gerardo Furtado is totally accurate, you should check it.

    Edit: As i already stated, and other users too, the async:false is not very good, so i'm editing my answer:

    function foobar() { 
        var json;
        loadJSON("data.json", function(response) {
            json = JSON.parse(response);
            // Call another function with json that is now filled with data
            triggered(json);
        });
    }
    
    function triggered(json) {
        console.log(json[0].name);
        // Do your work on json
    }