define("alpha", function(){ var _module = {}; _module.square = function(x){ return x*x; }; return _module; });
Asynchronous Module Definition specification, abbreviated as AMD, has been introduced in an attempt to define standards that facilitate asynchronous loading on client-side. It is largely inspired by Inversion of Control pattern, module in AMD could be seen as an equivalence of bean from IOC world.
Object dependencies, the most important aspect of IOC, are managed by an abstract container instead of the objects themselves. Such dependencies management model emerges its power in JavaScript world as:
There is possibility to defer resolution of dependencies (in term of JavaScript code) among JavaScript resources.
Deferring dependencies resolution implies that multiple JavaScript resources could be loaded asynchronously.
The API of AMD concerns two methods named define and require that are designed to declare and to use an AMD module from client-side.
A module identified as alpha that exposes square method at runtime is defined thanks to define method.
define("alpha", function(){ var _module = {}; _module.square = function(x){ return x*x; }; return _module; });
The function literal passed to define method plays the role of a module-factory function.
The base idea behind module definition could be expressed in a short message:
When i need alpha and if it is not available yet, please execute factory function and assign the result to alpha
/** * * The m-tuples (arg1, arg2,..., arg_k) takes the values (dependency_1, dependency_2,..., dependency_k), respectively. * */ define("module_id", ["dependency_1", "dependency_2",..., "dependency_k"], function(arg_1, arg_2,..., arg_k){ var _module = {}; //Complex code using arg_1, arg_2,..., arg_k return _module; });
Each module definition declares:
Module id.
Module dependencies.
Factory function to produce module object.
As the factory method is not executed immediately, multiple define blocks could be loaded into browser in an any order.
Execution of factory method (i.e. module object creation) is deferred until the module itself or one of its dependents (direct or non-direct) is required via require method.
/** * * The arguments (arg_1,..., arg_k) take the values (module_1, module_2,..., module_k), respectively. */ require(["module_1", "module_2",..., "module_k"], function(arg_1, arg_2,..., arg_k){ //Business code using arg_1, arg_2,..., arg_k };
Execution of require method consists of three phases:
Loading missing module definitions
In this phase, missing definitions of required modules are fetched/loaded into browser with the mechanism defined in implementation of AMD compliant library.
Resolving modules
In an order determined by dependency relations, factory method of each unavailable module is executed and the returned result is assigned to module id.
Callback execution
Once all required modules are available, the callback method function(arg_1, arg_2,..., arg_m) is invoked.
define("alpha", function(){ var _module = {}; _module.square = function(x){ return x*x; }; return _module; }); require(["alpha"], function($) { alert($.square(10)); //Alert message displays 10*10 = 100 });