前言
这个星期折腾了一周,中间没有什么时间学习,周末又干了些其它事情,这个时候正好有时间,我们一起来继续学习requireJS吧
还是那句话,小钗觉得requireJS本身还是有点难度的,估计完全吸收这个月就过去了,等requireJS学习结束后,我们的学习流程可能就朝两个方向走
① 单页应用框架/UI库整理
② UML文档相关/重构思想相关(软性素质)
然后以上的估计估计会持续3、4个月时间,希望学习下来自己能有不一样的提高,成为一个合格的前端,于是我们继续今天的内容吧
requireJS中的队列
经过之前的学习,我们队requireJS的大概结构以及工作有了一定认识,但是,我们对于其中一些细节点事实上还是不太清晰的,比如里面的队列相关
requireJS中有几种队列,每种队列是干神马的,这些是我们需要挖掘的,而且也是真正理解requireJS实现原理的难点
首先,requireJS有两个队列:
① globalDefQueue / 全局
② defQueue / newContext 闭包
这个队列事实上是一个数组,他们具体干了什么我们还不得而知,但是我下意识觉得他比较关键......
我们这里来简单的理一理这两个队列
globalDefQueue
这个是全局性的队列,与之相关的第一个函数为takeGlobalQueue
takeGlobalQueue
/**
* Internal method to transfer globalQueue items to this context's
* defQueue.*/
functiontakeGlobalQueue() {//Push all the globalDefQueue items into the context's defQueue
if(globalDefQueue.length) {//Array splice in the values since the context code has a
//local var ref to defQueue, so cannot just reassign the one
//on context.
apsp.apply(defQueue, [defQueue.length- 1, 0].concat(globalDefQueue));
globalDefQueue=[];
}
}
这个函数中涉及到了defQueue中的的操作,每一次有效操作后都会将全局队列清空,其中有一个apsp方法这个是数组的splice方法
该函数主要用于将globalDefQueue中的数据导入defQueue,而globalDefQueue只会有可能在define函数出被压入数据,具体原因还得往后看
所以这里的takeGlobalQueue其实就如注释所说,将全局队列中的项目转入context defQueue中
define
第二个涉及globalDefQueue函数为define
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.*/define= function(name, deps, callback) {varnode, context;//Allow for anonymous modules
if (typeof name !== 'string') {//Adjust args appropriately
callback =deps;
deps=name;
name= null;
}//This module may not have dependencies
if (!isArray(deps)) {
callback=deps;
deps= null;
}//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps &&isFunction(callback)) {
deps=[];//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
if(callback.length) {
callback
.toString()
.replace(commentRegExp,'')
.replace(cjsRequireRegExp,function(match, dep) {
deps.push(dep);
});//May be a CommonJS thing even without require calls, but still
//could use exports, and module. Avoid doing exports and module
//work though if it just needs require.
//REQUIRES the function to expect the CommonJS variables in the
//order listed below.
deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
}
}//If in IE 6-8 and hit an anonymous define() call, do the interactive
//work.
if(useInteractive) {
node= currentlyAddingScript ||getInteractiveScript();if(node) {if (!name) {
name= node.getAttribute('data-requiremodule');
}
context= contexts[node.getAttribute('data-requirecontext')];
}
}//Always save off evaluating the def call until the script onload handler.
//This allows multiple modules to be in a file without prematurely
//tracing dependencies, and allows for anonymous module support,
//where the module name is not known until the script onload event
//occurs. If no context, use the global queue, and get it processed
//in the onscript load callback.
(context ?context.defQueue : globalDefQueue).push([name, deps, callback]);
};
View Code
他会根据context是否初始化决定当前键值标识存于哪个队列,据代码看来,如果是标准浏览器应该都会先走globalDefQueue队列
然后就没有然后了,我们接下来再看看吧
defQueue
首先defQueue处于ne