patternjavascriptMinor
On demand JS loader review
Viewed 0 times
demandloaderreview
Problem
At my work, I need to create a script that third-party webmasters could include in their pages without need to include something else. But this script had dependencies on jQuery and some amount of their plug-ins.
On the Internet, I have found libraries that have same functionality except for an important one: they don't check are needed library already exist on a page.
Yes, I could execute the needed libraries in local scope of my script, but I've decided to reduce the number of HTTP connections and traffic with this function:
``
// instead of function
var lib_is_list = typeof(lib) === 'object';
if (typeof obj === 'function') obj = { callback: obj, count: lib_is_list ? lib.length : 1 }
if (lib_is_list) { // this is list of libs
for (var i in lib) require(lib[i], obj, libs_obj);
return;
}
var lib = libs_obj[lib];
if (lib.callbacks === undefined) lib.callbacks = [];
if (lib.check()) { if (obj.callback) obj.callback(); return; }
lib.callbacks.push(obj);
if (lib.pending) { return; }
lib.pending = true;
function ready() {
function script_downloaded() {
lib.pending = false;
var obj;
while (obj = lib.callbacks.pop()) {
obj.count--; if (obj.count == 0) obj.callback();
}
}
download_script(lib.link, script_downloaded);
}
function download_script(src, callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = 'async';
script.src = src;
// Based on jQuery jsonp trick
if (callback) {
script.onload = script.onreadystatechange = function() {
On the Internet, I have found libraries that have same functionality except for an important one: they don't check are needed library already exist on a page.
Yes, I could execute the needed libraries in local scope of my script, but I've decided to reduce the number of HTTP connections and traffic with this function:
``
var require = function (lib, obj, libs_obj) {
// if obj is function than require called directly by user and we
// must transform it to object. It's for reduce number of used
// variables. When we call require` recursively, we use this object// instead of function
var lib_is_list = typeof(lib) === 'object';
if (typeof obj === 'function') obj = { callback: obj, count: lib_is_list ? lib.length : 1 }
if (lib_is_list) { // this is list of libs
for (var i in lib) require(lib[i], obj, libs_obj);
return;
}
var lib = libs_obj[lib];
if (lib.callbacks === undefined) lib.callbacks = [];
if (lib.check()) { if (obj.callback) obj.callback(); return; }
lib.callbacks.push(obj);
if (lib.pending) { return; }
lib.pending = true;
function ready() {
function script_downloaded() {
lib.pending = false;
var obj;
while (obj = lib.callbacks.pop()) {
obj.count--; if (obj.count == 0) obj.callback();
}
}
download_script(lib.link, script_downloaded);
}
function download_script(src, callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = 'async';
script.src = src;
// Based on jQuery jsonp trick
if (callback) {
script.onload = script.onreadystatechange = function() {
Solution
My 2 cents:
Overal, I have to say this seems over-engineered, I think you are trying to be too smart.
- please use lowercase camelcase ( lib_is_list -> libIsList )
- The first 5 lines seem clumsy
- Checking for an array with typeof 'object' is odd
- Changing the type of a variable/parameter is odd and not recommended, you do this twice
- Dont drop newlines
( for (var i in lib) require(lib[i], obj, libs_obj); )
- You can use
lib.callbacks = lib.callbacks || []instead ofif (lib.callbacks === undefined) lib.callbacks = [];
- Why would you assign first callbacks, and then check() whether you should return
- Your handling of
obj,countandcallbacksis roundabout, the lack of newlines dont help,
- The function name
ready()is unfortunate,readyis most commly used for the callback after http requests
- You should consider merging/reworking
ready/script_downloaded/download_script
- The src parameter is unfortunate, since it does not contain the source, maybe url ?
- I like defensive programming, but checking for
callbackseems much, since your code guarantees it
Overal, I have to say this seems over-engineered, I think you are trying to be too smart.
Context
StackExchange Code Review Q#2324, answer score: 2
Revisions (0)
No revisions yet.