Konstantin Schubert
Konstantin Schubert

Reputation: 3356

Prevent re-loading of javascript if functions already exist. Otherwise ensure synchronous loading

Using JQuery.load(), I change the content of my website's mainWindow to allow the user to switch between tabs. For each tab, there is one or multiple scipts that contain functions that are executed once the tab content is loaded.

Obviously when switching to the tab for the first time, the script has to be fetched from the server and interpreted, but this shouldn't happen if the user switches back to the tab later on. So, to put it short:

  1. Load() html

  2. make sure javascript functions exist, otherwise load script and interpret it.

  3. call a a function on the javascript after the DOM is rebuilt.

Step one and two have to be complete before step 3 is performed.

At the moment, I am using nested callbacks to realize this:

function openFirstTab(){
    $("#mainWindow").load("firstTab.php", function(){
        if(typeof(onloadfFirstTab) != "function"){
            jQuery.getScript("assets/js/FirstTab.js", function(){
                onloadFirstTab();
            });
        }
        else{
            onloadFirstTab();
        }

    } );

}

but I feel that there should be a better way.

Upvotes: 2

Views: 2108

Answers (3)

Konstantin Schubert
Konstantin Schubert

Reputation: 3356

(Haven't tested it yet, so I am not sure if it works, especially since I didn't yet really understand scope in javascript:)

function require(scripts, callback){
var loadCount = 0;

function done(){
loadCount -=1;
if (loadCount==0){ 
    callback();
    }
}

for ( var script in scripts){
    if (!script.exitsts()){
        loadCount +=1;
        jQuery.getScript(script.url, done);
        }
}

}

This function takes an array of scripts that are required and makes sure all of them are interpreted before it calls the callback().

The "script" class:

function script(url, testFunc){
this.url =url;
this.testFunction = testFunc;
this.exists = function(){
if(typeof(testFunction)=="function"){
    return true;
    } 
else{
    return false;
    }
}
}

Where the test-function is a function that is defined (only) in the concerned script.

PS: To enable caching in JQuery and thus prevent the browser from doing a GET request every time getScript() is called, you can use one of the methods that are presented here.

Even though unnecessary GET - requests are avoided, the script is still getting interpreted every time getScript() is called. This might sometimes be the desired behavior. But in many cases, there is no need to re-interpret library functions. In these cases it makes sense to avoid calling getScript() if the required library functions are already available. (As it is done in this example with script.exists().

Upvotes: 0

dherman
dherman

Reputation: 2892

You can't write the code entirely synchronously since you can't load script synchronously after page load ( unless you do a synchronous XHR request and eval the results - not recommended ).

You've got a couple of choices. There are pre-existing dependency management libs like RequireJS which may fit the bill here, or if you just need to load a single file you can do something like this to clean up your code a bit rather than using if/else:

function loadDependencies() {
    // For the sake of example, the script adds "superplugin" to the jQuery prototype
    return $.getScript( "http://mysite.com/jquery.superplugin.js" );
}

function action() {
    // If superplugin hasn't been loaded yet, then load it
    $.when( jQuery.fn.superplugin || loadDependencies() ).done(function() {
        // Your dependencies are loaded now
    });
}

This makes use of jQuery Deferreds/Promises to make the code much nicer.

Upvotes: 2

jfriend00
jfriend00

Reputation: 707318

If you don't want to load the JS more than once and you are going to dynamically load it, then the only way to know whether it's already loaded is to test for some condition that indicates it has already been loaded. The choices I'm aware of are:

  1. The simplest I know of is what you are already doing (check for the existence of a function that is defined in the javascript).

  2. You could also use a property on each tab (using jQuery's .data() that you set to true after you load the script.

  3. You could write the dynamically loaded code so that it knows how to avoid re-initializing itself if it has already been loaded. In that case, you just load it each time, but the successive times don't do anything. Hint, you can't have any statically defined globals and you have to test if it's already been loaded before it runs its own initialization code.

Upvotes: 0

Related Questions