What is the best method for loading in dependencies & instantiating object only once in Javascript?

240
December 10, 2016, at 10:51 AM

I'd like to explore battle-tested, proven design patterns in Javascript that ensure loading in dependencies only once (if they were already loaded in) & instantiates an object only once as well in the DOM.

Specifically, i have following:

// Block A in the DOM
<script>
//instantiate my golden object as follows
var some_unique_options = {
   "option1": "some-val",
   "option2": "some-val"
     }
   $.ajaxSetup({cache:true});
   $.getScript('my_golden_script.js', function(){
        golden_object.init(some_unique_options);
    });
</script>
// Block B in the DOM
<script>
//instantiate my golden object as follows
var another_unique_options ={
    "option1": "some-val",
    "option2": "some-val"
   }
   $.ajaxSetup({cache:true});
   $.getScript('my_golden_script.js', function(){
        golden_object.init(another_unique_options);
   });
</script>

Currently, my golden_object implements a singleton as per: http://robdodson.me/javascript-design-patterns-singleton/

Intended behavior here is that, when the above Bock A & B execute top to bottom in the DOM, golden_object.init in Block B would leverage resources defined during the operation of Block A. Business requirement is as such that Block A & B would be identical, and there could be more in the DOM. After several days of researching, I'm still unable to come up with a solid structure. My singleton keeps re-creating itself as new, and only if i call golden_object.init(); in the devtools console, it would use the existing object in the DOM. How can i get this to work the way it's supposed to? what/where am i making a mistake here?

FYI, golden_object.js does carry $.fn.someOtherObj & couple of dependencies via $.getScript() as well as the definition of the singleton (i wanted Singleton obj to be user interface)

Million thanks to your insights & suggestions!

Answer 1

You could create a wrapper around jQuery.getScript that ensures the script is loaded only once, and, in the case of the second and further instances, calls the callback once the first script has loaded

jQuery.getScriptOnce = (function($) {
    var urls = {};
    return function(url, callback) {
        var obj = urls[url];
        if (!obj) {
            urls[url] = new Promise(function(resolve, reject) {
                $.getScript(url, function(script, textStatus, jqXHR) {
                    resolve({script: script, textStatus: textStatus, jqXHR: jqXHR});
                    callback(script, textStatus, jqXHR);
                });
            });
        } else {
            obj.then(function(val) {
                callback(val.script, val.textStatus, val.jqXHR);
            });
        }
    };
})(jQuery);

this has the benefit of only needing to change all occurrences of $.getScript to $.getScriptOnce

Note: I haven't checked to see if jQuery.getScript returns a jQuery promise, if it does, then the code can be a lot simpler

Just tested and it seems getScript DOES return a jquery promise - so you can simply do

jQuery.getScriptOnce = (function($) {
    var urls = {};
    return function(url) {
        return urls[url] = urls[url] || $.getScript(url);
    };
})(jQuery);

but you'll change

$.getScript('my_golden_script.js', function(){
    golden_object.init(some_unique_options);
});

to

$.getScriptOnce('my_golden_script.js').then(function(){
    golden_object.init(some_unique_options);
});
READ ALSO
jQuery conditional based on multiple selection

jQuery conditional based on multiple selection

I have two IDs and I would like to create a condition based on my query

309
ES6 - How to access `this` element after binding `this` class?

ES6 - How to access `this` element after binding `this` class?

How can I access this element after binding this class?

371
Jplayer jquery loader not working

Jplayer jquery loader not working

I have used Jplayer on my website to play songs onlineBelow I have mentioned the link of my website

358