首页 > 代码库 > extjs loader success callback源码

extjs loader success callback源码


首先,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源码