views:

37

answers:

4

I'm planning on getting several JS files from my server asynchronously while the page loads. I am aware of the Jquery function "getScript", but this only gets 1 script. Is there any way of specifying a callback to be executed when a batch of scripts have been fetched from the server?

I thought about doing something like this:

$.getScript(script1, function() {
$.getScript(script2, function() {
$.getScript(script3, function() {
...
...
});});....});

But this loads the scripts in sequence, and I'd like the requests to be done in parallel.

As a more general question which supersedes this one, what is the best way of loading N resources (CSS, images, scripts, etc) asynchronously specifying a single callback to be executed when all the resources have been loaded?

Update: In addition to this, I need the callback to be executed after the document is ready (signaled by the $(document).ready event). Any way of achieving this?

A: 
  1. Initialize a counter variable with number of resources to be fetched.
  2. Use the same callback for each asynchronous operation.
  3. This callback should decrease counter and check it's value. Once it gets to zero, it should invoke the code to be triggered on completion.
Adam Byrtek
+2  A: 

You need to call getScript 3 times in a row, passing a callback which increments a counter and calls the real callback if the counter is 3.

You can make a simple wrapper function to do this:

function getScripts(names, callback) {
    var received = 0;
    var realCallback = function() { 
        received++;
        if (received === names.length)
            $(callback);
    };

    for (var i = 0; i < names.length; i++)
        $.getScript(names[i], realCallback);
}

(Edited to call the callback when the document is ready)

You can call it like this:

getScripts([ "script1", "script2", "script3" ], function() { ... });
SLaks
This can be simplified by removing the counter, using `names.pop` (or `names.shift`) and checking to see if the length of the array is 0, rather than keeping track of the counter.
Ryan Kinal
@Ryan: That will be a little bit simpler, but (minutely) slower. Also, it means that the caller cannot reuse the array. (Which is unlikely anyway)
SLaks
This looks great, nice use of closures :)I'm facing a somehow related problem. I'd need to be able to determine which of the callback and $(document).ready are executed first. The thing is I need to execute code only when all the scripts have loaded (and executed) and the DOM has been completely parsed. I'll update the question to reflect this.
Diego
@Diego: Then you would change: `callback();` to `$(document).ready(callback);`
CD Sanchez
What happens if $(document).ready was executed before execution reaches that callback() line in the realCallback function? The callback wouldn't execute right?
Diego
@Diego: I am pretty sure that if the document is already loaded, the callback will be executed immediately.
CD Sanchez
You're right, I found it here:http://api.jquery.com/ready/Thanks!
Diego
A: 
var _couter=0;
var _calledScripts=0;
function _loadScripts(arrayOfScripts,_callBackFunction)
{
   _counter=arrayOfScripts.length;
   _calledScripts=0;
    jQuery.each(arrayOfScripts,function(index,item){
            jQuery.getScript(item, function(){
                _calledScripts++;
                if(_calledScripts==_couter)
                 {
                     _callBackFunction() 
                 }
             });
    });
}
Praveen Prasad
A: 

I use async.js to do this stuff:

async.map(scripts, $.getScript, function () {
    // called after all have completed...
});
Caolan