7

What is the basic difference between this 3 ways for lazy loading js or ondemand loading and why?

script 1:

$.getScript = function(url, callback, cache){
   $.ajax({
      type: "GET",
      url: url,
      success: callback,
      dataType: "script",
      cache: cache
   });
};

script2:

function require(file, callback) {
    var script = document.getElementsByTagName('script')[0],
        newjs = document.createElement('script');

    // IE
    newjs.onreadystatechange = function () {
        if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') {
            callback();
        }
    };

    // others
    newjs.onload = function () {
        callback();
    };

    newjs.src = file;
    script.parentNode.insertBefore(newjs, script);
}

document.getElementById('id').onclick = function () {
    require('ondemand.js', function () {
        extraFunction('loaded from the parent page');
        document.body.appendChild(document.createTextNode('done!'));
    });
};

script3:

$L = function (c, d) {
    for (var b = c.length, e = b, f = function () {
            if (!(this.readyState
                    && this.readyState !== "complete"
                    && this.readyState !== "loaded")) {
                this.onload = this.onreadystatechange = null;
                --e || d()
            }
        }, g = document.getElementsByTagName("head")[0], i = function (h) {
            var a = document.createElement("script");
            a.async = true;
            a.src = h;
            a.onload = a.onreadystatechange = f;
            g.appendChild(a)
        }; b;) i(c[--b])
};
Edson Medina
  • 9,862
  • 3
  • 40
  • 51
paul
  • 1,124
  • 9
  • 27
  • 45
  • If you wrote those functions, I hope you realize that `readyState == 'loaded'` happens *before* the script is executed, and `'complete'` happens *after*. – zzzzBov Aug 18 '11 at 19:00
  • yes true...even i am planning of just parsing the script and not execution since execution takes more time than parsing – paul Aug 18 '11 at 20:44

4 Answers4

7
  1. Uses ajax to load the script. More specifically it uses XHR to load some js and have it available to the browser. No blocking is done. It does still enforce the same origin policy.
  2. Modifies the header to inject a new .js file by creating <script/> element. This also doesn't block the browser on page load.
  3. Does the same thing as #2 but it seems to support an array of scripts. It also sets async to true which causes no blocking. The for loop is just more confusing because it creates a lot more anonymous methods.
Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • is there any issue with caching when we inject the scripts without ajax? function 1 since its XHR we can specify the cache:cache – paul Aug 18 '11 at 22:37
  • I think all of them could have that issue. The browser can even cache xhr requests. You can break the cache using a random query. If you control the server then you can choose to not cache. – Amir Raminfar Aug 18 '11 at 22:41
  • moreover if I am sending correct headers with expire date it shouldn't posses any issue ... – paul Aug 19 '11 at 14:30
  • With XHR you might be able to control that. I am not sure if you can control that with `` tag? – Amir Raminfar Aug 19 '11 at 14:49
2
  1. Seems to retrieves the script with a XmlHttpRequest and eval() it. This won't work if the script is not hosted on the same protocol / domain / port.

  2. and 3. seems to both do the same thing: they create a <script src="the script url"></script> element, bind onload events on it and insert it on the page. The script is executed by the browser once it is loaded, and the onload event is fired.

Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
  • what do you think about caching ? since in first function i can pass an property cache:cache whereas for other 2 case will it be a problem ? – paul Aug 18 '11 at 21:53
  • both methods are cache friendly, as long as the server send correct headers – Arnaud Le Blanc Aug 19 '11 at 08:32
2
  1. Gets the script via ajax, and eval()'s the contents
  2. Insert a script element into the head element and report back when it has loaded
  3. Same as (2) but accept and array of script urls, and is way more complexly written

(2) and (3) both use the onreadystatechange hook, which may not be compatible with older browsers (for instance, Firefox 3.x and below doesn't support it).

(1) is probably the most robust, compatibility-wise, since it just requires XHR. But if you get errors in the code you load that way, the browser's console may not be very helpful, as the error just occurred in "eval'd code" and not in a specific file/line. That said, lazy loading is typically an optimization thing, so you can just include the scripts normally, or with any of the other 2 methods, while debugging.

Flambino
  • 18,507
  • 2
  • 39
  • 58
1

you should try this new library called head.js

they have some interesting ideas and apis.. hope it helps.

or what you can do is use the normal xhr request to get your script file names and use a method like this to insert into the dom.. I have added the removeScript part too.

addScript = function(file)
{
    var headID = document.getElementsByTagName("head")[0];         
    var newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = file;
    headID.appendChild(newScript);
};
removeScript = function(file)
{
    var headID = document.getElementsByTagName("head")[0].children;
    for(var i in headID)
        if(headID[i].tagName == "SCRIPT")
            if(headID[i].getAttribute('src') == file)
                headID[i].parentNode.removeChild(headID[i]);
}

if you are using a library like jquery you dont need to worry about anything you can get the html or script markup from the server and use .html() api to in insert it into the dom

Ruud Helderman
  • 10,563
  • 1
  • 26
  • 45
Baz1nga
  • 15,485
  • 3
  • 35
  • 61
  • This should be a comment since it dosen't actually answer anything. – Amir Raminfar Aug 18 '11 at 19:06
  • @zzzz yes I look through head.js, labjs and controljs but trying to come up with my own solution instead of using an another library – paul Aug 18 '11 at 20:46
  • what did u think of the addScript method? – Baz1nga Aug 18 '11 at 20:48
  • this is similar to what I am doing ...accept you have a removeScript function ..By why do you need this function since once you load the script it will be in browser cache and helps in better performance when you revisited ... – paul Aug 18 '11 at 21:51