灏天阁

异步模块模式

· Yin灏
/**
 * 异步模块
 * 浏览器环境不同于服务器环境,在浏览器中对文件的加载是异步的。因此要使用未加载文件中的某些模块方法时必然经历文件的加载过程,因此对未加载文件中的模块引用,同步模块模式是无能为力的。
 */

/**
 * 异步模块
 * 如创建 Event 模块,但要涉及 DOM,你可以这样使用 F.module('lib/event, ['lib/dom'], function(dom) {})
 * 第一个参数是('lib/event)是模块 id,一定要对应文件路径
 */

// 闭包环境
// 目的是封闭已创建的模块,防止外界对其直接访问,并在闭包中创建模块管理器 F,并作为接口保存在全局作用域中

// 向闭包中传入模块管理器对象 F(~屏蔽压缩文件时,前面漏写,报错)
~(function (F) {
  // 模块缓存器,存储已创建的模块
  var moduleCache = {};
})(
  (function () {
    // 创建模块管理器对象 F,并保存在全局作用域中
    return (window.F = {});
  })()
);

/**
 * 创建与调度模块
 * 这里的 module 方法集模块创建方法于一身,在这个方法中要遍历所有依赖模块,并判断所有模块都存在才可执行回调函数,否则加载相应文件,直到文件加载完成才执行回调函数。
 */

/**
 * 创建或调用模块方法
 * @param {*} url  模块 url
 * @param {*} modDeps  依赖模块
 * @param {*} modCallback 模块主函数
 */
F.module = function (url, modDeps, modCallback) {
  // 将参数转化为数组
  var args = [].slice.call(arguments),
    // 获取模块构造函数,参数数组中最后一个参数成员
    callback = args.pop(),
    // 获取依赖模块,紧邻回调函数参数,且数据类型为数值
    deps =
      args.length && args[args.length - 1] instanceof Array ? args.pop() : [],
    // 该模块 url,模块 ID
    url = args.length ? args.pop() : null,
    // 依赖模块序列
    params = [],
    // 未加载的依赖模块数量统计
    depsCount = 0,
    // 依赖模块序列中索引值
    i = 0,
    // 依赖模块序列长度
    len;
  // 获取依赖长度
  if ((len = deps.length)) {
    // 遍历依赖模块
    while (i < len) {
      // 闭包保存 i
      (function (i) {
        // 增加未加载依赖模块数量统计
        depsCount++;
        // 异步加载依赖模块
        loadModule(deps[i], function (mod) {
          // 依赖模块序列中添加依赖模块接口引用
          params[i] = mod;
          // 依赖模块加载完成,依赖模块数量统计减一
          depsCount--;
          // 如果依赖模块全部加载
          if (depsCount === 0) {
            // 在模块缓存器中矫正该模块,并执行构造函数
            setModule(url, params, callback);
          }
        });
      })(i);
      // 遍历下一依赖模块
      i++;
    }
  } else {
    // 无依赖模块,直接执行回调函数
    setModule(url, [], callback);
  }
};

- Book Lists -