Ext create动态加载分析

时间:2024-01-01 18:13:57

主要涉及到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;
}
},