首先,Loader有几个重要的属性
queue: [] 存放所有主文件类信息,包括他的依赖文件信息,结构如下:
[{requires: ‘Seed.view.MainGrid‘
callback: callback // Loader.require(dependencies,function(){});中的function
}]
注意:所有的动态加载文件信息都会被放到队列中
isLoading: 是否在加载
numLoadedFiles: 已经加载完成文件数
numPendingFiles: 待加载文件数
seriptsLoading: 正在加载的文件数
isClassFileLoaded: {} 对象存储了所有的类以及他们是否已经被加载了当文件加载、解析完成会调用回调方法:
if (‘addEventListener‘ in script ) {
script.onload = onLoadFn;
} else if (‘readyState‘ in script) { // for <IE9 Compatability
script.onreadystatechange = function() {
if ( this.readyState == ‘loaded‘ || this.readyState == ‘complete‘ ) {
onLoadFn();
}
};
} else {
script.onload = onLoadFn;
}回调方法,之前也有所涉及,如下:
onFileLoaded: function(className, filePath) {
var loaded = isClassFileLoaded[className]; // 文件是否已经被加载过
Loader.numLoadedFiles++; // 已加载数量加1
isClassFileLoaded[className] = true; // 标记文件被加载过
isFileLoaded[filePath] = true;
// In FF, when we sync load something that has had a script tag inserted, the load event may
// sometimes fire even if we clean it up and set it to null, so check if we‘re already loaded here.
if (!loaded) { // 如果文件之前没有被加载过,那么待加载数减1
Loader.numPendingFiles--;
}
if (Loader.numPendingFiles === 0) { // 当待加载数为0
Loader.refreshQueue();
}
// missingClasses的处理,略
}当待加载数量为0的时候,执行Loader.refreshQueue(),如下:
refreshQueue: function() {
var ln = queue.length,
i, item, j, requires;
// When the queue of loading classes reaches zero, trigger readiness
if (!ln && !Loader.scriptsLoading) { // ,递归的结束条件:加载队列为空
return Loader.triggerReady(); // triggerReady见下面
}
for (i = 0; i < ln; i++) { // 循环队列中的每一个对象
item = queue[i];
if (item) {
requires = item.requires;
// Don‘t bother checking when the number of files loaded
// is still less than the array length
if (requires.length > Loader.numLoadedFiles) {
continue;
}
// Remove any required classes that are loaded
for (j = 0; j < requires.length; ) {
if (Manager.isCreated(requires[j])) { // 如果某个item的依赖类A已经被创建了,则从item的require中移除他
// Take out from the queue
arrayErase(requires, j, 1);
}
else {
j++;
}
}
// If we‘ve ended up with no required classes, call the callback
if (item.requires.length === 0) { // 当某个类的所有依赖文件都已经被加载,那么从队列中移除该item
arrayErase(queue, i, 1);
item.callback.call(item.scope);
Loader.refreshQueue();// 递归
break;
}
}
}
return Loader;
}refreshQueue()方法的作用,是不停的循环检测,直到所有的类都被加载、执行、创建,之后调用triggerReady()方法,如下:
triggerReady: function() {
var listener,
refClasses = usedClasses;
if (Loader.isLoading) {
Loader.isLoading = false;
if (refClasses.length !== 0) { // 加载用use关键字引用的路径
// Clone then empty the array to eliminate potential recursive loop issue
refClasses = refClasses.slice();
usedClasses.length = 0;
// this may immediately call us back if all ‘uses‘ classes
// have been loaded
Loader.require(refClasses, Loader.triggerReady, Loader);
return Loader;
}
}
Ext.Array.sort(readyListeners, comparePriority);// listener排序
// this method can be called with Loader.isLoading either true or false
// (can be called with false when all ‘uses‘ classes are already loaded)
// this may bypass the above if condition
while (readyListeners.length && !Loader.isLoading) { // 逐个调用回调方法
// calls to refreshQueue may re-enter triggerReady
// so we cannot necessarily iterate the readyListeners array
listener = readyListeners.shift();
listener.fn.call(listener.scope);
}
return Loader;
}从这里看出:use关键字依赖的类,要等其他关键字依赖的类都加载成功之后才加载。
本文出自 “技术人生” 博客,请务必保留此出处http://wangyuelucky.blog.51cto.com/1011508/1604695
extjs loader success callback源码
原文地址:http://wangyuelucky.blog.51cto.com/1011508/1604695