cipher
cipher

Reputation: 2484

Cannot parse JSON?

Here's my javascript file

var callAjax = function(relative_path){
        var Ajax =  new XMLHttpRequest();
            Ajax.onreadystatechange = function() {

                //Since what we are calling a local file. we cannot get a 200 OK Status.
                //So We check only the readystate
                if(Ajax.readyState==4){
                    serialized = Ajax.responseText;
                    alert(serialized); 
                    // ^^ alerts fine.
                    return serialized;
                }

            }

            Ajax.open("GET",relative_path, true);
            Ajax.send();    
};


var readSettings = function(){
    var data = callAjax('settings.json');
    obj  = JSON.parse(data);
    alert(obj);
}

Now when i call readSettings() somewhere in my html, the first alert (in the callAjax functions alerts the JSON correctly. but the second one does not. When i see the console, the error is :

[21:04:02.233] SyntaxError: JSON.parse: unexpected character @ file:///home/cipher/Codes/looma-f5/js/looma.js:23

My settings.json is:

{

    "classes": 8,
    "config": "classConfig",
    "locale": {
        "en": "localeEn"
    },
    "defaultLocale": "en"
}

I ran the JSON through online tools, it looks good. Why is firefox not parsing these?

Upvotes: 0

Views: 2093

Answers (3)

Blue Skies
Blue Skies

Reputation: 2975

You're not returning any value from the callAjax function. You need to put your code that uses the result inside the onreadystatchange handler.

You do have a return statement, but it's inside the callback, which returns to the internal caller of the callback, and which is invoked after your callAjax returned.

Since it seems that callAjax is fairly generic, a good approach is to have that function accept a callback as an argument, then invoke it, passing in the response.

//                  receive a callback----vv
var callAjax = function(relative_path, callback){
        var Ajax =  new XMLHttpRequest();

        Ajax.onreadystatechange = function() {
            if(Ajax.readyState==4){
                serialized = Ajax.responseText;
                alert(serialized); 

                // vv---invoke the callback
                callback(serialized);
            }
        }
        Ajax.open("GET",relative_path, true);
        Ajax.send(); 
};

var readSettings = function(){
    // pass a callback ----------------------vv
    var data = callAjax('settings.json', function(data) {
        var obj  = JSON.parse(data);
        alert(obj);
    });
}

If the caller of readSettings needs to work with the response, then you could have readSettings also receive a callback, and then either pass it on directly, or wrap it in another function so that it can first do the parsing.

I'll give an example that assumes that it needs to be wrapped.

// receive a callback----------vv
var readSettings = function(callback){
    // pass a callback that wraps the first---vv
    var data = callAjax('settings.json', function(data) {
        // parse the response data
        var obj  = JSON.parse(data);

        // invoke the callback, passing it the parsed object
        callback(obj);
    });
}

readSettings(function(settings_obj) {
    alert(settings_obj);
});

Upvotes: 3

nandhp
nandhp

Reputation: 4817

The "A" in AJAX is for asynchronous. After submitting the XMLHttpRequest, the callAjax function will return immediately, without waiting for the request to complete. Thus, the JSON.parse will be called with the return value of callAjax (which isn't the JSON you're looking for), generating the error.

Some time later, the XMLHttpRequest will complete and the onreadystatechange callback will be run. You return the JSON from this function, but the JSON doesn't go anywhere because it's returning from the callback, not from callAjax.

You must perform the JSON parsing and subsequent activities as a result of the onreadystatechange event.

Upvotes: 1

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143299

The problem is that you can JSON.parse immediately after callAjax returns. Before the onreadystate callback is executed. Due to asynchronous nature of the operation you should trigger parsing from the callback.

Upvotes: 2

Related Questions