Ext create动态加载分析

主要涉及到Ext.js Inventory.js ClassManager.js Class.js Loader.js Boot.js

在ClasManager.js的Ext.create中

Ext.syncRequire(name); // 加载类的js

Loader.js 中

syncRequire: function () {
            var wasEnabled = Loader.syncModeEnabled;

            Loader.syncModeEnabled = true;

            var ret = Loader.require.apply(Loader, arguments);

            Loader.syncModeEnabled = wasEnabled;

            return ret;
        },
 require: function (expressions, fn, scope, excludes) {
            if (excludes) {
                return Loader.exclude(excludes).require(expressions, fn, scope);
            }

            var classNames = Manager.getNamesByExpression(expressions);

            return Loader.load(classNames, fn, scope);
        },
load: function (classNames, callback, scope) {
            if (callback) {
                if (callback.length) {
                    // If callback expects arguments, shim it with a function that will map
                    // the requires class(es) from the names we are given.
                    callback = Loader.makeLoadCallback(classNames, callback);
                }
                callback = callback.bind(scope || Ext.global);
            }

            var state = Manager.classState,
                missingClassNames = [],
                urls = [],
                urlByClass = {},
                numClasses = classNames.length,
                url, className, i, numMissing;
            
            for (i = 0; i < numClasses; ++i) {
                className = Manager.resolveName(classNames[i]);
                
                if (!Manager.isCreated(className)) {
                    missingClassNames.push(className);
                    
                    if (!state[className]) {
                        urlByClass[className] = Loader.getPath(className);
                        urls.push(urlByClass[className]);
                    }
                }
            }
            
            // If the dynamic dependency feature is not being used, throw an error
            // if the dependencies are not defined
            numMissing = missingClassNames.length;
            
            if (numMissing) {
                Loader.missingCount += numMissing;
                
                Manager.onCreated(function () {
                    if (callback) {
                        Ext.callback(callback, scope, arguments);
                    }
                    
                    Loader.checkReady();
                }, Loader, missingClassNames);

                if (!_config.enabled) {
                    Ext.raise("Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
                             "Missing required class" + ((missingClassNames.length > 1) ? "es" : "") + 
                             ": " + missingClassNames.join(', '));
                }

                if (urls.length) {
                    Loader.loadScripts({
                        url: urls,
                        // scope will be this options object so we can pass these along:
                        _classNames: missingClassNames,
                        _urlByClass: urlByClass
                    });
                }
                else {
                    // need to call checkReady here, as the _missingCoun
                    // may have transitioned from 0 to > 0, meaning we
                    // need to block ready
                    Loader.checkReady();
                }
            }
            else {
                if (callback) {
                    callback.call(scope);
                }
                
                // need to call checkReady here, as the _missingCoun
                // may have transitioned from 0 to > 0, meaning we
                // need to block ready
                Loader.checkReady();
            }
            
            if (Loader.syncModeEnabled) {
                // Class may have been just loaded or was already loaded
                if (numClasses === 1) {
                    return Manager.get(classNames[0]);
                }
            }

            return Loader;
        },
/**
         * This is an internal method that delegate content loading to the 
         * bootstrap layer.
         * @private
         * @param params
         */
        loadScripts: function(params) {
            var manifest = Ext.manifest,
                loadOrder = manifest && manifest.loadOrder,
                loadOrderMap = manifest && manifest.loadOrderMap,
                options;
            
            ++Loader.scriptsLoading;
            
            // if the load order map hasn't been created, create it now 
            // and cache on the manifest
            if (loadOrder && !loadOrderMap) {
                manifest.loadOrderMap = loadOrderMap = Boot.createLoadOrderMap(loadOrder);
            }

            // verify the loading state, as this may have transitioned us from
            // not loading to loading
            Loader.checkReady();

            options = Ext.apply({
                loadOrder: loadOrder,
                loadOrderMap: loadOrderMap,
                charset: _config.scriptCharset,
                success: Loader.onLoadSuccess,
                failure: Loader.onLoadFailure,
                sync: Loader.syncModeEnabled,
                _classNames: []
            }, params);

            options.userScope = options.scope;
            options.scope = options;

            Boot.load(options);
        },

在Boot.js中

load: function (request) {
                //<debug>
//                 _debug("Boot.load called");
                //</debug>
                var request = new Request(request);

                if (request.sync || Boot.syncMode) {
                    return Boot.loadSync(request);
                }

                // If there is a request in progress, we must
                // queue this new request to be fired  when the current request completes.
                if (Boot.currentRequest) {
                    //<debug>
//                     _debug("current active request, suspending this request");
                    //</debug>
                    // trigger assignment of entries now to ensure that overlapping
                    // entries with currently running requests will synchronize state
                    // with this pending one as they complete
                    request.getEntries();
                    Boot.suspendedQueue.push(request);
                } else {
                    Boot.currentRequest = request;
                    Boot.processRequest(request, false);
                }
                return Boot;
            },
 loadSync: function() {
            var me = this;
            me.fetch({
                async: false,
                complete: function (response) {
                    me.onContentLoaded(response);
                }
            });
            me.evaluate();
            me.notifyRequests();
        },
        fetch: function (req) {
            var url = this.getLoadUrl(),
                async = !!req.async,
                complete = req.complete;

            Boot.fetch(url, complete, this, async);
        },

最终网络通讯在这

fetch: function(url, complete, scope, async) {
                async = (async === undefined) ? !!complete : async;

                var xhr = new XMLHttpRequest(),
                    result, status, content, exception = false,
                    readyStateChange = function () {
                        if (xhr && xhr.readyState == 4) {
                            status = (xhr.status === 1223) ? 204 :
                                (xhr.status === 0 && ((self.location || {}).protocol === 'file:' ||
                                    (self.location || {}).protocol === 'ionp:')) ? 200 : xhr.status;
                            content = xhr.responseText;
                            result = {
                                content: content,
                                status: status,
                                exception: exception
                            };
                            if (complete) {
                                complete.call(scope, result);
                            }
                            xhr.onreadystatechange = emptyFn;
                            xhr = null;
                        }
                    };

                if (async) {
                    xhr.onreadystatechange = readyStateChange;
                }

                try {
                    //<debug>
//                     _debug("fetching " + url + " " + (async ? "async" : "sync"));
                    //</debug>
                    xhr.open('GET', url, async);
                    xhr.send(null);
                } catch (err) {
                    exception = err;
                    readyStateChange();
                    return result;
                }

                if (!async) {
                    readyStateChange();
                }

                return result;
            },

            notifyAll: function(entry) {
                entry.notifyRequests();
            }
        };
complete函数定义在这
onContentLoaded: function (response) {
            var me = this,
                status = response.status,
                content = response.content,
                exception = response.exception,
                url = this.getLoadUrl();
            me.loaded = true;
            if ((exception || status === 0) && !_environment.phantom) {
                me.error =
                    //<debug>
                    ("Failed loading synchronously via XHR: '" + url +
                        "'. It's likely that the file is either being loaded from a " +
                        "different domain or from the local file system where cross " +
                        "origin requests are not allowed for security reasons. Try " +
                        "asynchronous loading instead.") ||
                    //</debug>
                    true;
                me.evaluated = true;
            }
            else if ((status >= 200 && status < 300) || status === 304
                || _environment.phantom
                || (status === 0 && content.length > 0)
                ) {
                me.content = content;
            }
            else {
                me.error =
                    //<debug>
                    ("Failed loading synchronously via XHR: '" + url +
                        "'. Please verify that the file exists. XHR status code: " +
                        status) ||
                    //</debug>
                    true;
                me.evaluated = true;
            }
        },


 
原文地址:https://www.cnblogs.com/coolzdp/p/7468738.html