4

I have a webpage that will load a couple JSON files via XMLHttpRequest.
I want to load the file, parse the JSON and store the output in a globally accessible variable.
Once BOTH foo and bar are complete, only then do I want to call the success() function. So far, my script has 2 problems that I need help with.

1: I'm having trouble setting the variable to the output of loadJSON(). My guess is that my return statements are a little funky? I've tried everything... help?

2: How do I call success() only AFTER BOTH foo and bar are set?

var foo;
var bar;

function initSession(){

    foo = loadJSON("foo.js");
    bar = loadJSON("bar.js");

}

My guess is that the problem lies in how I'm using return in the loadJSON() function:

function loadJSON(url){

    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){  
            return JSON.parse(xhr.responseText);  // doesn't work?
        }
    }

    xhr.open("GET", url, true);
    xhr.send();

    return xhr.onreadystatechange;
}



$(document).ready(function(){
    initSession();
});


function success(){ 
    $("body").append(foo[0]);  
    $("body").append(bar[0]);  
}

Thank you!

Prophet
  • 32,350
  • 22
  • 54
  • 79
p1xelarchitect
  • 289
  • 1
  • 6
  • 19
  • The `return JSON.parse(xhr.responseText)` is not working because it's asynchronous and you can assign the result into a global var in that callback function usinf `varname = JSON.parse(xhr.responseText)` but this may not solve the problem. – The Alpha Jun 09 '14 at 11:07
  • so how can I call success() only after BOTH foo and bar are set? – p1xelarchitect Jun 09 '14 at 11:11

2 Answers2

3

For anyone who discovers this in the future... below was my final solution based on the discussion in the accepted answer. which would easily allow an extension to dynamically set the number of files before the success function is called.

var foo;
var bar;
var count = 0;

function initSession(){

    loadJSON("foo.js", "foo");
    loadJSON("bar.js", "bar");   

}

function loadJSON(url, name){

    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function(){

        if(xhr.readyState == 4 && xhr.status == 200){  
            count++;
            window[name] = JSON.parse(xhr.responseText);;

            if (count == 2){
                success();
            } 
        }
    }

    xhr.open("GET", url, true);
    xhr.send();
}



$(document).ready(function(){
    initSession();
});



function success(){ 
    $("body").append(foo[0].option + "<br>" + bar[0].fname + " " + bar[0].lname);  
}
p1xelarchitect
  • 289
  • 1
  • 6
  • 19
1

You may try something like this:

$(document).ready(function(){
    loadJSON("foo.js");
    loadJSON("bar.js");
});

Modify your success function:

function success(data){ 
    $("body").append(data[0]);  
}

Then modify in your success callback/onreadystatechange

if(xhr.readyState == 4 && xhr.status == 200){  
    success(JSON.parse(xhr.responseText));
}

Call the success function from success callback/onreadystatechange function. Also you can pass a callback function to loadJSON function and can call that callback function from the onreadystatechange/success callback, for example:

function loadJSON(url, callback){

    // ...

    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){  
            callback(JSON.parse(xhr.responseText));
        }
    }

    // ...
}

Then you may pass the callback function like this:

loadJSON("foo.js", function(data){
    // do something with data
});

So, you can use different callback functions for different ajax requests.

The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • 1
    yes, this works... but the idea is that I don't want to load success until BOTH foo and bar have reached a readyState of 4... – p1xelarchitect Jun 09 '14 at 11:19
  • The `success` global function will be called once at a time after the data is returned, so there would be no problem. – The Alpha Jun 09 '14 at 11:21
  • I think I might not be understanding you properly... i don't want to call success once at a time. I only want to call it once. after loadJSON() is complete for both files. – p1xelarchitect Jun 09 '14 at 11:23
  • 1
    [Check this thread](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call). – The Alpha Jun 09 '14 at 11:25
  • Actually `success` will be called every time the ajax request succeeded and data returned from the server, so `success` will be called twice for two `ajax` requests. So the `$("body").append(data[0]);` will be executed only when data is returned from the server. – The Alpha Jun 09 '14 at 11:27
  • 2
    If you want to call the success only once then instead of calling the success from the `onreadystatechange` you may keep/store the returned response to a variable and on the second successful `ajax` call, call the `success` function. – The Alpha Jun 09 '14 at 11:30
  • that's a great point to count the number of success callbacks! i'm trying that now – p1xelarchitect Jun 09 '14 at 11:43
  • Adding a callback to loadJSON() is a good idea.. but your previous suggestion to count the successes worked for me! – p1xelarchitect Jun 09 '14 at 11:53
  • I've accepted your answer. thanks! but - i added my final solution as another answer. thanks for your help! – p1xelarchitect Jun 09 '14 at 11:58