The seajs module depends on loading and module execution, and the seajs module depends on loading.

Source: Internet
Author: User
Tags hasownproperty

The seajs module depends on loading and module execution, and the seajs module depends on loading.

This article describes how to load dependencies between seajs modules and how to execute modules. The following is a detailed introduction.

Entry Method

Each program has an entry method, similar to c'smainFunctions and seajs are no exception. Series 1 demo is used on the homepageseajs.use() This is the entry method. The entry method can take two parameters. The first parameter is the module name, and the second parameter is the callback function. The entry method defines a new module, which depends on the module provided by the input parameter. Set the callback function of the new moduleloadedStatus. This callback function is mainly used to execute the factory functions of all dependent modules, and finally the callback provided in the execution entry method.

// Public API // The endpoint seajs. use = function (ids, callback) {Module. preload (function () {Module. use (ids, callback, data. cwd + "_ use _" + cid ()}) return seajs} // Load preload modules before all other modulesModule. preload = function (callback) {var preloadmod = data. preload var len = preloadmod. length if (len) {Module. use (preloadmod, function () {// Remove the loaded preload modules preloadmod. sp Lice (0, len) // Allow preload modules to add new preload modules Module. preload (callback)}, data. cwd + "_ preload _" + cid ()} else {callback ()} // Use function is equal to load a anonymous moduleModule. 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 =cmd.exe c ()} // the return value of the dependent module corresponding to the input parameter of the callback function if (callback) {callback. apply (global, exports)} delete mod. callback} mod. load ()}

Module.preloadIt is used to pre-load plug-ins provided by seajs. It is not a major function and can be ignored. WhileModule.useThis is the core method. As mentioned earlier, this method creates a new module, sets the callback function, and loads all the dependent modules of the new module.

Load Method for dependency Loading

loadThe method is the essence of seajs. This method mainly loads the dependent module and executes the callback function of the dependent module in sequence.seajs.use(“./name”)Callback of the newly created module, that ismod.callback.

loadRecursively load the dependency module. If the dependency module is dependent on other modules, load the module again. This is throughModuleClass_waitingsAnd_remain.

Module. prototype. load = function () {var mod = this // If the module is being loaded, just wait onload call if (mod. 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 len = 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 dependency file's _ waiting attribute if (m. status <STATUS. LOADED) {// Maybe duplicate: When module has dupliate dependency, it shocould be it's count, not 1 m. _ waitings [mod. uri] = (m. _ waitings [mod. uri] | 0) + 1} else {mod. _ remain --} // load the dependency and execute the module if (mod. _ remain = 0) {mod. onload () return} // Begin parallel loading var requestCache ={} for (I = 0; I <len; I ++) {m = cachedmod [uris [I] // If the dependency is not loaded, fetch and seajs. the request function is bound to the corresponding requestCache. At this time, the module if (m. status <STATUS. FETCHING) {m. fetch (requestCache)} else if (m. status = STATUS. SAVED) {m. load ()} // Send all requests at last to avoid cache bug in IE6-9. issues #808 // load all modules for (var requestUri in requestCache) {if (requestCache. hasOwnProperty (requestUri) {// load the module requestCache [requestUri] ()} // After the dependency Module is loaded, run the callback function. // check whether other modules dependent on the Module can execute the 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 = cachedmod [uri] m. _ remain-= waitings [uri] if (m. _ remain = 0) {m. onload () }}// Reduce memory taken delete mod. _ waitings delete mod. _ remain}

First, initialize_waitingsAnd_remainProperty, if_remainIf the value is 0, it means that no dependency or dependency has been loaded and can be executed.onloadFunction. If the value is not 0fetchUnloaded modules. Here is a small implementation technique, that is, loading all dependencies at the same time:requestCacheObject Storage and Loading Function: (INfetchDefined in the function)

if (!emitData.requested) { requestCache ?  requestCache[emitData.requestUri] = sendRequest :  sendRequest() }

Where,sendRequestThe 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, executeonRequestCallback, bubble up, load dependency until no dependency module is available.

RunonloadFunction, in which the status is setloaded, Executemod.callback,Check and set_waitingsAttribute to determine whether there is any dependency on the lower-level module. If not, executemod.callback, This tracing will eventually passseajs.useThe created anonymous Modulemod.callback.

Example

A simple example is provided to illustrate the above process:

tst.html<script>  seajs.use('./b');</script>-------------------------------------a.jsdefine(function(require,exports,module){ exports.add = function(a,b){  return a+b; }})------------------------------------b.jsdefine(function(require,exports,module){ var a = require("./a"); console.log(a.add(3,5));})

The debugging tool shows that the executiononloadOrder:

Finally, we can see that the status code of the anonymous module is 4, that is, this module has not been executed. Indeed, it has not defined the factory function for the anonymous module and cannot be executed.

Exec for module execution

The module is executed inseajs.useDefined inmod.callbackAnd call all dependentexecMethod to execute the program logic.execMethods include some important keywords or functions of commonJS, suchrequire,exportsAnd so on. Let's take a look at the following:

Module.prototype.exe c = function () {var mod = this // When module is executed, do not execute it again. when module // is being executed, just return 'module. exports 'too, for avoiding // circularly calling if (mod. status> = STATUS. EXECUTING) {return mod. exports} mod. status = STATUS. EXECUTING // Create require var uri = mod. uri function require (id) {return module.get(require.resolve(id1_0000.exe c ( )} Require. resolve = function (id) {return Module. resolve (id, uri)} require. async = function (ids, callback) {Module. use (ids, callback, uri + "_ async _" + cid () return require} // Exec factory var factory = mod. factory // if the factory function has a return value, return; // if there is no return value, return mod. exports var exports = isFunction (factory )? Factory (require, mod. exports = {}, mod): factory if (exports = undefined) {exports = mod. exports} // Reduce memory leak delete mod. factory mod. exports = exports mod. status = STATUS. EXECUTED // Emit 'exec 'event emit ("exec", mod) return exports}

requireFunction gets the module and executes the module's factory function to obtain the return value.requireFunctionresolveThe method is to obtain the absolute url of the corresponding module name,requireFunctionasyncThe method asynchronously loads the dependency and executes the callback. For the return value of the factory method, if the factory method is an object, this isexportsOr if the factory method has a return value, it isexportsValue;or module.exportsIsexports. When you can obtainexportsValue, set the statusexecuted.

Note:If you wantexportsWhen assigning values to export an object

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

It is unsuccessful. we can judge the final export by executing the above method.exportsFirst, the function does not return values. Second,Mod. exports is undefined, The final exportedexportsIsundefined. Why is this happening? This is because the value assignment is referenced in js. The assignment policy of js is "transfer by share", although the initialexports === module.exportsBut whenexportsWhen an object is assignedexportsPoint to this object,module.exportsBut still not initialized,undefined.

The correct statement is as follows:

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

Summary

It can be said that the implementation of the core module of seajs has been explained, and many coding skills have been learned, the clever callback mode, and the careful consideration. Every part of the Code has taken into account the risk of Memory leakage and this pointer reference offset, and has been actively prevented. this spirit is worth learning.

For seajs, it took me less than a week to read the source code. from the beginning to the present, I really understood the importance of design ideas. Previously, I did not pay much attention to the implementation skills and thought that it could be implemented without bugs and robust. But now I realize that something is wrong, especially in the implementation of the load dependency module, skillful. The above is all the content of this article. I hope the content of this article will help you in your study or work. If you have any questions, please leave a message.

Related Article

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.