This is a quickie how-to post to help address a couple little gotchas you may run into when implementing LABjs onto your site.
Consider standard page code like this:
<script src="framework.js"></script> <script src="myscript.js"></script> <script> myscript.init(); </script> <script> framework.init(); framework.doSomething(); </script>
In this example, “myscript.init” is a function that is defined in “myscript.js”, and “framework.init” and “framework.doSomething” are both defined inside of “framework.js”.
The first pass at implementing LABjs to load these scripts may seem like this code would work correctly:
<script>
$LAB
.script("framework.js")
.script("myscript.js")
.wait(myscript.init); // won't work!
</script>
<script>
framework.init(); // also won't work
framework.doSomething(); // also won't work
</script>
Why is my function reference undefined?
Firstly, the code “.wait(myscript.init)” seems like this is the correct way to tell LABjs to run “myscript.init” function after the scripts finish loading. But there’s a subtle problem: with regular <script> tags, the inline script block in the first snippet that has “myscript.init()” in it is guaranteed to not even be EVALUATED before the scripts synchronously have loaded before it. So, “myscript.init” is guaranteed to have been defined by that point, so it will work as expected.
But, in the second snippet, we pass a reference to “myscript.init” into the wait() function. But, “myscript.init” hasn’t been defined yet, because the chain for LABjs will execute immediately, as it starting to load the scripts. This means that at the time that .wait(…) first gets parsed, “myscript.init” doesn’t exist. It will be defined, later, when the scripts finish, but the reference is undefined at that point, and thus cannot be used yet.
So, the simple way to fix this problem is this:
<script>
$LAB
.script("framework.js")
.script("myscript.js")
.wait(function(){ myscript.init(); });
</script>
<script>
framework.init();
framework.doSomething();
</script>
So, what we pass to “wait” is not a reference to the as-of-yet-undefined “myscript.init”, but an anoynmous function that will call/execute “myscript.init()” at the proper time. Because of how functions and closures and execution bindings work in JavaScript, this syntax will wait to try to resolve/execute “myscript.init()” until that function is guaranteed to have been loaded (because “myscript.js” finished loading!).
It’s a simple but devious concept in JavaScript… the difference between a function reference “myscript.init” and an anonymous function that will call the intended function later “function(){myscript.init();}”.
OK, but I still have undefined code
For the exact same reason that “myscript.init” wasn’t yet defined when we tried to pass it to .wait(…), the code in the second inline <script> block, the calls to “framework.init()” and “framework.doSomething()”, those scripts do not yet exist (are undefined) at the moment the inline script block in question executes (which would be immediately after the first parse of the $LAB chain, but before either of its scripts have arrived).
So, we have to put THAT code into a .wait(…) as well, so that it waits to be parsed/executed until the right time.
<script>
$LAB
.script("framework.js")
.script("myscript.js")
.wait(function(){
myscript.init();
framework.init();
framework.doSomething();
});
</script>
We could do two separate .wait(…) calls, but that’s unnecessary in this example, so I just combine the two sets of inline code into one wait() function.
Think asynchronously
The key issue is the difference between immediately executing code (like in the original inline <script> tags) and the need to defer asynchronously executing code, by wrapping it in an anonymous function reference. This is because LABjs, by definition, loads scripts asynchronously, as opposed to regular <script> tags which are synchronous.
It may take a couple of tries before you wrap your brain completely around this stuff. But the basic pattern you can default to applying when replacing <script> tags with LABjs calls is this:
- For every <script src=”…”></script> tag you are replacing, you should have a “.script(…)” call
- For every <script>…/*inline code*/…</script> inline script block with code in it, we need a “.wait(function(){ … })” call to wrap around the code
Hopefully that helps clear up some confusion you may run into!


Hi,
I’ve been trying to work with LABjs and JQuery plugins simultaneously in a project.
All other inline code (like ckeditor’s replace call, simple alerts, etc.) seem to work fine with LABjs but I still am having problems with handling jquery validate plugin using LABjs.
The code snippet I am using is:
$LAB .script("jquery.1.4.2.js") .block(function(){ $LAB .script("jquery.validate.js") .wait(function(){ // -- validate ruleset and messages which works // normally with IE too $("#form1").validate({ // -- rules and messages }); }) });// —
normally, I was using the same script with the following convention:
$(document).ready(function(){ $("#form1").validate({ // -- rules and }); });and it was working fine with all browsers till I started using LABjs.
I suppose I’ve made a very silly mistake there, but what can I do? The examples you have included in your website and even the LABjs documentation all show only simple inline code handling!
Please help!!
Thanks in advance,
Arun
Try this:
$LAB .script("jquery.1.4.2.js").wait() .script("jquery.validate.js").wait(function(){ $(document).ready(function(){} $("#form1").validate({ // -- rules and messages }); }); });Hi again,
Many thanks for your response!
I downloaded the latest release of jquery.validate (1.7, I was using 1.6 with jquery.1.4.2) and this problem went away!
I’m in love with LABjs speeds up loading like magic!!!
Also, is it ok if I avoid jquery DOM ready as much as I can? Because I assume any process that I need to do at document ready could be done at the end of the $LAB chain with a .wait(function(){}); block.
Please suggest.
Thanks a lot again!
And sorry to have bothered you for jquery.validate’s incompatibility issue.
Hope you don’t mind
Thanks
Arun
@Arun-
Glad you got the jquery.validate issue squared away. But please also be aware that your technique of using $LAB chains nested inside of .wait/.block calls is less efficient. You should try to write it as all one big chain with .script and .wait calls interspersed. For instance:
$LAB.script(…).wait(…).script(….).script(….).wait(…)……
You’re doing stuff like this and it’s less efficient:
$LAB.script(….).wait(function(){ $LAB.script(….).wait(…)…. })……
Do you see the difference?
Secondly, the “.block” is a deprecated name for “.wait”, so you should always use .wait, not .block. And make sure you’re using LABjs 1.0.2rc1, which is the latest stable available version.
Also, do *not* assume that a $LAB.wait() call is equivalent to waiting for dom-ready. The dom-ready event is entirely separate from the dynamic loading of scripts, so you may have sometimes where the dom-ready happens before the scripts finish, and other times the reverse. So you should always use $(document).ready() to protect any code which relies on the presence/readiness of the DOM.
Hi,
Many thanks for the brief insight! I will keep it in mind.
Also, I really think that there are a lot of novice labjs users who are confused like I’ve been. Could you please post some links to examples of LABjs used with various javascript libraries like jquery , yui etc. ?
I had a very hard time coming across examples of labjs on the internet.
Also, I thought I was doing the right thing loading dependent group of scripts (e.g., jquery.validate, jquery.form, etc.) into a single .block (I’ll use .wait now on though) that would load after the jquery library is loaded.
Looking at your example above, I think I still am not 100% sure.
Due to the dependency of validate and jquery form upon jquery, I assume the following would be efficient – I am assuming that validate and form will both loading in parallel after jquery.js finishes loading :
–
$LAB
.script(‘jquery.js’).wait(function(){$LAB.script(‘jquery.validate.js’).wait().script(‘jquery.form.js’)})
But you stated above:
–
$LAB
.script(‘jquery.js’).wait().script(‘jquery.validate.js’).script(‘jquery.form.js’).wait();
which looks much simpler than expected! So if I am assuming it wrong and the example you’ve given is how it should be, I suppose I can write documentready function at the earliest possible .wait ? i.e., after adding a .wait right behind .script(‘jquery.validate.js’) ?
Also, once again, please could you post some links that you could be helpful and save you the hassle?
Thanks
@Arun- unfortunately, I don’t know of any great examples out there other than this blog post and perhaps a few articles strewn about. I’m still the main person promoting how LABjs actually works. Hope eventually more others will pick up the mantle.
To try and clarify for you: A single $LAB chain consists of a starting $LAB followed by a chain of one or more .script() calls and .wait() calls, interspersed as you need them to be. You should always try to avoid *multiple* $LAB calls, as they operate completely independently. Also, by nesting a $LAB inside a .wait(), you prevent that chain from even *loading* until the .wait() has executed. By doing a single chain with all your scripts, LABjs can load them *all* in parallel, but control their execution order based on where you have .wait() calls. That’s what .wait() is for, to ensure *execution* order.
As for your $document.ready()… the use of $document.ready() is entirely separate from and orthagonal to the order of your scripts loading. It is only for making sure some logic doesn’t run until the dom is ready. LAB script loads *do not* affect dom readiness at all (they don’t hold it up) so there’s no connection that you should make between sequencing $LAB with document.ready.
Instead, you should load all your scripts with LABjs and use .wait() where it’s most appropriate to run code. If that code happens to be dependent on the dom-readiness, wrap the code (inside your .wait()) with a document.ready. In some cases, your scripts may load and execute before dom-ready, and thus your logic will protected to run later when the dom is ready. In other cases, dom-ready will pass before your scripts load and execute, and using document.ready() will essentially pass through and execute immediately.
If the code you need to wrap in $(document).ready() only cares about jquery, and not about the plugins, then do this:
$LAB .script("jquery.js") .wait(function(){ $(document).ready(function() { /* do something */ }); }) .script("plugin1.js") .....If the code you have to run needs the plugin to be there, then do it this way:
$LAB .script("jquery.js") .wait() .script("plugin1.js") .wait(function(){ $(document).ready(function() { /* do something */ }); });Does that make sense more now?
Great!
Thank you so much! I guess I referred to quite old posts to have used .block.
The one I’d referred to here :
http://ajaxian.com/archives/labjs-simple-abstraction-for-loading-dependencies-correctly
–
said quite clearly in the example:
old=>
new=>
$LAB .script("jquery.js") .block(function(){ $LAB .script("jquery.ui.js") .script("myplugin.jquery.js") .block(function(){ $LAB.script("initpage.js"); }); });I know its wrong now.
Thank you again
I think I’m clear about it now.
Thanks a lot again!
I had a similar problem with multiple inline script blocks, but I was unable to combine them into one because they came from different components. After I realized the chain was instance based, I “continued” the chain by keeping the reference in a global variable, and using it in my future inline script block.
Here’s this posts sample code, rewritten with my technique:
var instance = $LAB .script("framework.js") .script("myscript.js") .wait(function(){ myscript.init(); }); instance.wait(function(){ framework.init(); framework.doSomething(); });Hi
We have the following scenario on our site where we want to combine an “if” statement (in the example below, we’re checking the variable “allowExternalScripts”) with loading in script files. I’ve read your comments on trying to only have one occurence of $LAB in the code but haven’t been able to work out a way to include further script files once an operator has executed as part of the $LAB flow. Do you have any suggestions how this could be refined (ideally 4 & 5 would be combined as I expect initPage could be called before 4 has finished)?
// 1 var postInitPage = function() { if (allowExternalScripts) { $LAB .block() .script(document.location.protocol + '//external-file-c.js') .script(document.location.protocol + '//external-file-d.js'); } } // 2 function initDom() { // initialise DOM elements here } // 3 function initPage() { $(document).ready(function() { initDom(); postInitPage(); }); } // 4 if (allowExternalScripts) { $LAB .block() .script(document.location.protocol + '//external-file-a.js') .script(document.location.protocol + '//external-file-b.js'); } // 5 $LAB .script(document.location.protocol + '//internal-file-a.js') .block() .script(document.location.protocol + '//internal-file-b.js') .script(document.location.protocol + '//internal-file-c.js') .script(document.location.protocol + '//internal-file-d.js') .script(document.location.protocol + '//internal-file-e.js') .block(function() { initPage(); });Many thanks
Tom
@Tom-
If I understand you correctly, I think this blog post helps explain how you might accomplish this:
http://blog.getify.com/2010/02/simulated-chaining-in-javascript/
Also, note that $LAB.block() is never a correct pattern, as “block” should never be the first function call in a $LAB chain. I imagine you’re probably doing that because you’re trying to “continue” the previous chain, but unfortunately you’re not doing that, you’re creating a new chain. The above link shows you how you can programatically build up a chain with whatever conditional logic you want, and then simulate the chain with a for-loop, which I imagine will accomplish the goal you have of extending a current chain based on conditional logic. Have a look and lemme know if that helps.
Lastly, note that “block” is now a deprecated API call, replaced with “wait”. The next version of LABjs will not have “block” anymore.