Question

I have the following scenario...

$.when(
    $.getScript('script.js')
).done(function () {
    if ( scriptIsAlreadyLoaded ) {
        // I want to cancel this promise.
        // I no longer want script.js because
        // it has already been loaded in another
        // instance.
    }

    // I dont' want this to run if the above
    // condition is true.
    doStuff();
});

I understand that doing this inside done() doesn't make much sense since, by definition, it's too late to cancel the promise.

So what would be the best approach here?

NOTE: This snippet could be executed multiple times. This is why I want to avoid the script from being loaded more than once.

Was it helpful?

Solution

It makes no sense to cancel a promise inside the .done() handler. When the .done() handler is called the operation is already complete (it sounds like maybe you already know that). So, when your .done() handler is called, the load of your script has already completed. There is nothing left to cancel.

If you just want to prevent your own code from trying to load the script multiple times, then you don't really use promises for that. You could just keep track of your own flag or you could test the environment to see if the script is already present. For example, you could use this function that checks to see if there is a script tag loaded already that ends with a particular filename:

function isScriptPresent(fname) {
    var regex = new RegExp(fname + "$");
    var scripts = document.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
        if (regex.test(scripts[i].src)) {
            return true;
        }
    }
    return false;
}

if (!isScriptPresent("script.js")) {
    $.getScript("script.js");
}

Or, you could make your own getScript function that would first check to see if it was already loaded:

$.getScriptIfNotLoaded = function(fname) {
    if (!isScriptPresent(fname)) {
        return $.getScript(fname);
    }
}

Then, you could just do:

$.getScriptIfNotLoaded("script.js");

and, it would never be loaded multiple times in the same page. This has the advantage that it doesn't matter how the script was first loaded (even if it was in the original HTML) - this will find it if it's already in the page.


You could also just keep track of what has been loaded in a map:

(function() {
    var loadedScripts = {};

    $.loadScriptOnce = function(fname) {
        if (!loadedScripts[fname]) {
            loadedScripts[fname] = true;
            return $.getScript(fname);
        }
    };
})();

$.loadScriptOnce("scripts.js");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top