0

I am working on asynchronous calls with $.getScript which will load the scripts I need for specific pages. I grab the scripts via an AJAX call to get the scripts I need and then load them in order with the $.when function, I am not sure why the .done() calls immediately, not when the scripts have loaded entirely and placed in the DOM, ready to be used.

For example, the AJAX call returns this:

['js/jquery.cookie.js', 'js/leaflet.js', 'js/index.js']

With this code:

var loadScripts = function(callback)
{
    $.getJSON('url.php', function(response)
    {
        $['when'].call(this, response).done(function()
        {
            callback();
        });
    });
};

Calling it by:

loadScripts(function()
{
    // All scripts are loaded and ready to use
    // but the callback is fired immediately

    // L is undefined
    var map = L.map('map-view').setView([51.505, -0.09], 13);
});

I don't want to use a library such as Head.js or Require.js, I need a simple script that can load and wait till the loaded functions are in place that can be used. Please note that the scripts list can change and the order as well, so doing $.when($.getScript(), $.getScript()).done() won't be what I am looking for.

How can I approach this?

MacMac
  • 34,294
  • 55
  • 151
  • 222

1 Answers1

1

Your ajax call is returning an array of strings, not deferred objects. You need to actually make those strings deferred objects by requesting them with jQuery.getScript and storing the return value.

var loadScripts = function(callback) {
    $.getJSON('url.php', function(response) {
        var defArr = $.map(response,function(url) {
            return $.getScript(url);
        });
        $.when.apply($, defArr).done(callback);
    });
};​
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Okay, that's great. However when calling the function with the callback function scope, I want to call a function from the file, when I call, it says undefined, but if I wrap inside a `setTimeout` of 2 seconds, it will work. This is what I have a problem with because I need it to wait till the function is ready to use. – MacMac Dec 06 '12 at 19:22
  • does it also work with a settimeout of 0 seconds? this would tell you whether it's simply a timing issue, or if it really is firing too early. – Kevin B Dec 06 '12 at 19:31
  • That doesn't make sense then. the .done should not be fireing before the code is done loading/executing. something else may be going on not related to this code. Confirm that the array (`defArr`) is an array of objects that contain a `promise` method. – Kevin B Dec 06 '12 at 19:35
  • I get an `object` with the AJAX functions. – MacMac Dec 06 '12 at 19:39
  • See my edit, stupid mistake. It should be `.apply`, not `.call`. doh – Kevin B Dec 06 '12 at 19:42
  • Wow, that's awesome. Good job mate! – MacMac Dec 06 '12 at 19:44
  • Oh, one thing I have to ask. When I refresh the page a couple times, not rapidly, just once every 10 seconds or so when I've changed code of the loaded scripts, sometimes it doesn't fire it after it loaded them, sometimes its fine. Why is this? (I have `$.ajaxSetup({ cache: false })` before the `$.getScript` so caching is not the issue? – MacMac Dec 06 '12 at 20:37
  • Have you inspected the network traffic to see if all of the scripts successfully loaded? We have that problem here occasionally due to what i think is network issues. – Kevin B Dec 06 '12 at 20:39
  • Yeah, they always load with status code 200, so nothing wrong with the network issues? – MacMac Dec 06 '12 at 20:46
  • But would it differ if it was on a real site than localhost? – MacMac Dec 06 '12 at 20:51
  • @BurningtheCodeigniter I don't know. – Kevin B Dec 06 '12 at 20:54