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.preload
Used 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
load
Method 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
.
load
method 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. exec
There 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}
require
function 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.