Introduction to Asynchronous Module Dependency in JavaScript with RequireJS

Why AMD?

The AMD format comes from wanting a module format that was better than today’s “write a bunch of script tags with implicit dependencies that you have to manually order” and something that was easy to use directly in the browser. Something with good debugging characteristics that did not require server-specific tooling to get started. It grew out of Dojo’s real world experience with using XHR+eval and and wanting to avoid its weaknesses for the future.
It is an improvement over the web’s current “globals and script tags” because:
Uses the CommonJS practice of string IDs for dependencies. Clear declaration of dependencies and avoids the use of globals.
IDs can be mapped to different paths. This allows swapping out implementation. This is great for creating mocks for unit testing. For the above code sample, the code just expects something that implements the jQuery API and behavior. It does not have to be jQuery.
Encapsulates the module definition. Gives you the tools to avoid polluting the global namespace.
Clear path to defining the module value. Either use “return value;” or the CommonJS “exports” idiom, which can be useful for circular dependencies.
It is an improvement over CommonJS modules because:
It works better in the browser, it has the least amount of gotchas. Other approaches have problems with debugging, cross-domain/CDN usage, file:// usage and the need for server-specific tooling.
Defines a way to include multiple modules in one file. In CommonJS terms, the term for this is a “transport format”, and that group has not agreed on a transport format.
Allows setting a function as the return value. This is really useful for constructor functions. In CommonJS this is more awkward, always having to set a property on the exports object. Node supports module.exports = function () {}, but that is not part of a CommonJS spec.

culled from RequireJS

Now we will create a simple application called nairaland application what it does is simply list all the banned members from the Database(obviously lietral objects) but we will do it in a manner that is modular and easy to do.
first create a simple html.

<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
Now that we have the html file,we need to download the RequireJS library, for Dojo user it comes with Dojo but this is a general tutorial so no dojo involved here.
RequireJS Library

Download the require.js file and in the html add the file with the tag
<script src="require.js" type="text/javascript"></script> Next we need to create the nairaland application so we create a js file called “nairaland.js”

define(["banned"],function(e){

  var obj= {
    forum:"Nairaland",
    country:"Nigeria",
    type:"Open Forum",
    owner:"Seun Orewa",
    hasMultiRooms:true,
    bannedMembers:e.getBannedMember()
    
  };

  return obj;
});
What “define” does is to create a module,you have the option of passing a function if you need to setup some connections,now because i want the module to just simply return an object, i passed a function which returns “obj”,if you look at the first parameter it has an array argument with the name “banned”, the banned refers to a dependency,meaning a file that this nairaland will require before it returns the nairaland object,think of it as php include and java import.While the files loads the result of the file is being passed as an argument to the callback,this is an asynchronous operation because we have no idea when the file will finish, a callback is registered, once it finish it passes the result as an argument to the callback function.The “banned.js” will simply be a (class or Object or a Module) in the first parameter, so before i jump into that let’s create the “banned” class first.

Banned Class
we will create another file called “banned.js”

define(function(){
        //bannedMembers is a literal Object that holds an array which holds an Objects of data which represents our banned Entity in Real Life Applications these source can from Ajax,LocalStorage or even SqLite
  var bannedMembers={
    list:[{
        name:"dhtml",
           meta:{
      reason:'attempting to hack nairaland and spanbot-killer',
      banned_durations:'2 weeks',
      limited_access:'true'
          }

        },
        {
        name:"yawatode",
           meta:{
      reason:'too much SEO advise :',
      banned_durations:'2 weeks',
      limited_access:'true'
          }

        },
        {
        name:"donpuzo",
           meta:{
      reason:'Disturbing potential female programmers on nairaland',
      banned_durations:'4 weeks',
      limited_access:'true'
          }

        },
         {
        name:"omo_to_dun",
           meta:{
      reason:'SpamBot personal reason',
      banned_durations:'4 weeks',
      limited_access:'true'
          }

        }]
  }

      
    

//create an object that returns a the list through the use of Closure
return {
  getBannedMember:function(){
    return bannedMembers.list;
  }
};
});
As usual we create the define to create a module, then pass a function because i dont want the nairaland class to have access to the list so i return an object with a function “getBannedMember” that returns the list data through the help of a Closure. “Closure is a complicated thing to explain”,now our banned module will return an object with the method getBannedMember which is just a simple literal objects of keys and value. lets jump back to “nairaland.js”.
define(["banned"],function(e){

}
because the banned file is in the same folder i just simply use the name “banned” which will translate to banned.js

now our “e” is the result of banned.js which is our object now thanks to this pattern i no longer have to worry about my empty object being attached to Global object,”e” is my banned Object which returned after loading the “banned.js”.
e.getBannedMember() so i now have access to the method with ease and this is awesome because if i wanted to change the implementation i can easily go to banned.js and change what i what.

How to Use in the HTML Page

//You can attach this to a jQuery Ready or Document.onload function when the DOM is ready to use
require(["nairaland"],function(a){
//code goes here
});
this will load nairaland.js which in turn will also load banned.js,dependency files are always loaded first so no more worries about the order of placing scripts like jquery users usually face when they put the “jquery.js” after a Script that uses jQuery.
require(["nairaland"],function(a){ //remember a is the nairaland object
                //a.bannedMembers takes the list from the return method of getBannedMembers so a.bannedMembers is an array

                //an array has a function forEach that allows you iterate over its item it takes a function with item as the argument
    a.bannedMembers.forEach(function(item){
                //this will get the div with the id list
    var doc=document.getElementById('list');
                //appends to the html values from the object
    doc.innerHTML+='<p>Banned Member Name:'+item.name+'</p><hr />';
                //now remember that the banned members is an array of objects in each item in the array is an object with name and meta and meta
                //is also an object so we traverse/scan each property in the meta object
               //for in is used for objects where i the property, you should know that function is also a property think of it as a hash dictionary obj['onclick']

                //dump our datas and thats all
    for(var i in item.meta){
      doc.innerHTML+="<p><strong>"+i+"</strong>=>"+item.meta[i]+"</p>";
    }
    doc.innerHTML+="<hr />";
      
    });
  });

NOTE: i have attached the files for this Tutorial, you might ask why bother ? well you should bother if you really love to write clean codes and also a little bit of secret; getting comfy with AMD is a step closer to learning all frameworks even NodeJS as most frameworks are adopting the AMD pattern, even the DojoToolkit.

Resources

Download Source

Web developer,Php Zend and Javascript Dojo coder,and am in love with Enya. And lover of dark arts and alcohol. I hope to learn C php extensions and NodeJS. and i can't live without a PS3 :D

Leave a Reply

Your email address will not be published. Required fields are marked *