require.js源码分析

时间:2022-04-02 10:04:29

在整个require中,主要的方法就两个:require和define,我们先来看require

require

require作为主函数来引入我们的“模块”,require会从自身的的存储中去查找对应的defined模块,如果没有找到,则这时这个模块有可以存在三种状态:loading, enabling, defining
这就是require中要注意的地方,如果模块还没有被加载,那么它的这三种状态出现的时机是:

  • loading 文件还没有加载完毕
  • enabling 对该模块的依赖进行加载和模块化
  • defining 对正在处理的模块进行加载,并运行模块中的callback

require的load方法的主要代码:

req.load = function (context, moduleName, url) {
  var config = (context && context.config) || {},
  node;
  if (isBrowser) {
    //create a async script element
    node = req.createNode(config, moduleName, url);
    //add Events [onreadystatechange,load,error]
    .....
    //set url for loading
    node.src = url;
    //insert script element to head and start load
    currentlyAddingScript = node;
    if (baseElement) {
      head.insertBefore(node, baseElement);
    } else {
      head.appendChild(node);
    }
    currentlyAddingScript = null;
    return node;
  } else if (isWebWorker) {
    .........
  }
};
req.createNode = function (config, moduleName, url) {
  var node = config.xhtml ?
    document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
    document.createElement('script');
  node.type = config.scriptType || 'text/javascript';
  node.charset = 'utf-8';
  node.async = true;
  return node;
};

node上设定了 async 属性(异步加载script标签),并且在标签上绑定了load等事件,当文件loading完成后,则要做的主要工作是执行 completeLoad 事件函数,但是要注意的是这时候把script加载完成后,立即执行的是script标签内部的内容,执行完后才触发的 completeLoad事件,而在我们的模块里面,一定要用define函数来对模块进行定义,所以这里我们先穿插着来讲讲define干了什么