SEAJS module dependencies between load and module execution _SEAJS

Source: Internet
Author: User
Tags anonymous emit hasownproperty

This article describes the Seajs module dependencies between the load and the implementation of the module, the following words are not more directly to see the detailed introduction.

Entry method

Each program has an entry method, a function similar to C main , and Seajs is no exception. The demo of series one is used in the homepage seajs.use() , this is the entrance method. The entry method can accept 2 parameters, the first parameter is the module name, and the second is the callback function. The entry method defines a new module that is dependent on the module provided by the parameter in the new module. The callback function of the new module is then set up to be loaded invoked after the state. The callback function is primarily the factory function that executes all dependent modules, and finally the callback provided by the Execute entry method.

Public API//ENTRY Address Seajs.use = function (IDs, callback) {Module.preload (function () {Module.use (IDs, callback, data.) CWD + "_use_" + CID ())} return Seajs}//Load preload modules before all other modules module.preload = function (cal
  Lback) {var preloadmods = data.preload var len = preloadmods.length if (len) {module.use (preloadmods, function () { 
  Remove the loaded preload modules Preloadmods.splice (0, Len)//Allow preload-modules to add new preload modules Module.preload (Callback)}, DATA.CWD + "_preload_" + CID ())} else {callback ()}}//Use function's equal to L 

 Oad a anonymous module module.use = function (IDs, callback, URI) {var mod = Module.get (URI, IsArray (IDs)? IDs: [IDs]) Mod.callback = function () {var exports = [] var URIs = Mod.resolve () for (var i = 0, len = uris.length; i < len ; i++) {Exports[i] = cachedmods[uris[i]].exec ()}//callback function argument corresponds to the return value of the dependent module if (callback) {callback.apply (Global, export s)} Delete mod.calLback} mod.load ()} 

Module.preloadUsed to preload the SEAJS provided by the plugin plugins, which is not a major feature that can be ignored. It Module.use is the core method, which, as previously stated, creates a new module and sets the callback function, and finally loads all the dependent modules of the new module.

Load method of loading dependencies

loadMethod is the essence of SEAJS. The method mainly loads the dependent module and sequentially executes the callback function of the dependent module, and the final callback function is the callback of the seajs.use(“./name”) new module created by the mod.callback .

loadmethod to load the dependent module recursively, and then load the module if the dependent module also relies on other modules. This is accomplished by the Module and in the class _waitings _remain .

Module.prototype.load = function () {var mod = this//If the ' module is being loaded, just wait it onload call If (Mo D.status >= status. LOADING) {return} Mod.status = status. LOADING//Emit ' Load ' event for plugins such as combo plugin var URIs = mod.resolve () Emit ("Load", URIs, MoD) var l  En = Mod._remain = uris.length var m//Initialize modules and register waitings for (var i = 0; i < len; i++) {m = Module.get (Uris[i])//Modify the _waiting property of the dependent file if (M.status < status.  LOADED) {//Maybe Duplicate:when module has dupliate dependency, it should is it ' s count, not 1 M._waitings[mod.uri] = (M._waitings[mod.uri] | | 0) + 1} else {mod._remain--}}//Load dependent, execute module if (Mod._remain = = 0) {mod.onload (

 return}//Begin parallel loading var requestcache = {} for (i = 0; i < len; i++) {m = Cachedmods[uris[i]] The dependency is not loaded, then the Seajs.request function is bound to the corresponding Requestcache, and the module if (M.status < status) is not loaded at this time. Fetching) {M.fetch (Requestcache)
 else if (m.status = = status. SAVED) {m.load ()}//Send all requests at the last to avoid cache bug in ie6-9.
  issues#808//Load all modules for (Var requesturi in Requestcache) {if (Requestcache.hasownproperty (RequestUri)) {//load module at this time  Requestcache[requesturi] ()}}//dependent module loading completes the callback function//and checks whether other modules that depend on the module can perform Module.prototype.onload = function () {var MoD = this mod.status = status. LOADED if (mod.callback) {mod.callback ()} console.log (MoD)//Notify waiting-modules to fire onload var waitings = mod._waitings var uri, M for (URI in waitings) {if (Waitings.hasownproperty (URI)) {m = Cachedmods[uri] M._rema  In-= Waitings[uri] if (M._remain = = 0) {m.onload ()}}}//Reduce memory taken delete mod._waitings Delete Mod._remain}

Initializing the and properties of the module first _waitings _remain , if _remain 0, means that there is no dependency or dependency loaded, can execute the function, and onload if not 0, the fetch module is not loaded. The trick here is to load all dependencies at the same time: requestCache object Save load Function: ( fetch defined in function)

if (!emitdata.requested) {
 requestcache?
  Requestcache[emitdata.requesturi] = sendrequest:
  sendrequest ()
 }

Where the sendRequest function is defined as follows:

function SendRequest () {
 seajs.request (Emitdata.requesturi, Emitdata.onrequest, Emitdata.charset)
 }

Load all dependencies in parallel, when the dependencies are loaded, execute the onRequest callback, bubble up, load dependent dependencies until no dependent modules are installed.

When the topmost dependency has no dependencies on the module, execute the onload function, set the state in the function body loaded , execute mod.callback, and check and set the properties of the module _waitings , determine if the underlying module is still dependent, and if it does not execute the lower module mod.callback , this sequence of backtracking, Will eventually execute through the seajs.use anonymous module that was created mod.callback .

Example

The above process is demonstrated by a simple example:

tst.html

<script>
  seajs.use ('./b ');
</script>
-------------------------------------
a.js

define (function (Require,exports,module) {
 Exports.add = function (a,b) {return
  a+b;
 }
})
------------------------------------
b.js

define (function (require,exports,module) {
 var a = require (". a");
 Console.log (A.add) (3,5);
})

The order of execution can be seen through the Debugging tools onload :

Finally, the status code of the anonymous module is 4, which means the module is not executed. Indeed, no factory function was defined for the anonymous module and cannot be executed.

exec of module execution

Module execution is invoked in the seajs.use defined in mod.callback , calling all dependent methods in turn exec , executing program logic. execThere are some important keywords or functions of commonjs in the method, such as require , exports let us look at the following:

Module.prototype.exec = function () {var mod = this//when the module is executed, does not execute it again. When module//are being executed, just return ' module.exports ' too, for avoiding//circularly calling if (Mod.status & Gt;= STATUS. Executing) {return mod.exports} mod.status = status.
 Executing//Create require var URI = Mod.uri function require (ID) {return module.get (Require.resolve (ID)). EXEC () } Require.resolve = function (ID) {return module.resolve (ID, uri)} Require.async = function (IDs, callback) {Modul E.use (IDs, callback, Uri + "_ASYNC_" + CID ()) return require}//Exec factory var factory = mod.factory//factory function has returned
  Value, returns mod.exports var exports = Isfunction (Factory) If no return value is returned; Factory (require, Mod.exports = {}, MoD): Factory if (exports = = undefined) {exports = Mod.exports}//Reduce m Emory Leak Delete Mod.factory mod.exports = exports mod.status = status. Executed//Emit ' EXEC ' event Emit ("exec", MoD) return ExpoRTS} 

requirefunction to get the module and execute the module's factory function to get the return value. The method of a require function resolve is to get the absolute URL of the corresponding module name, and the require method of the function async asynchronously loads the dependency and executes the callback. For the return value of the factory method, this is the value if the factory method is an object, or the value of the exports or factory method with the return value exports ; or module.exports exports When a value can be obtained exports , the setting state is executed .

It is worth noting that when you want to exports export an object by assigning a value

Define (function (require,exports,module) {
 exports ={
  add:function (a,b) {return
    a+b;
  }
 }
)

is unsuccessful. We use the above method to determine exports the value of the final export. First, the function does not return a value, and secondly, the mod.exports为undefined final export exports is undefined . Why is this happening? is due to the reference assignment in JS. JS's assignment strategy is "by sharing", although initially exports === module.exports , but when an object is assigned, the object is still uninitialized, exports exports module.exports undefined and therefore an error occurs.

The correct wording is

Define (function (require,exports,module) {
 module.exports ={
  add:function (a,b) {return
    a+b;
  }
 }
)

Summarize

It can be said that the implementation of the core modules of Seajs has been explained, learned a lot of coding skills, appreciate the clever callback mode, as well as the details of the consideration. Every place in the code takes into account the dangers of memory leaks and the this pointer reference offset, and it is worth learning to do proactive prevention.

For Seajs, back and forth spent less than one weeks to read the source code, from the beginning of a smattering to today's kneel, I really understand the importance of design ideas. I didn't pay much attention to the skill of implementation, I think it can be achieved, no bugs, good robustness, but now I realize that the wrong, especially in the load dependency module that part of the implementation, the skill is full. The above is the entire content of this article, I hope the content of this article for everyone's study or work can bring some help, if you have questions you can message exchange.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.