自己边读变加了一些注释,理解了一下seajs3.0.0工作的流程。正则没有一个个去理解,插件模块也没看, 以后有时间了可以补充完整~

var list = events[name] || (events[name] = [])

以前自己写都是

if(!events[name]){
    events[name]=[];
}
var list=events[name];

加载模块文件的方法

webworker环境下加载模块文件

获取seajs的加载路径:

var stack;
  try {
    var up = new Error();
    throw up;
  } catch (e) {
    // IE won't set Error.stack until thrown
    stack = e.stack.split('\n');
  }
//  at Error (native) <- Here's your problem
//  at http://localhost:8000/_site/dist/sea.js:2:4334 <- What we want
//  at http://localhost:8000/_site/dist/sea.js:2:8386
//  at http://localhost:8000/_site/tests/specs/web-worker/worker.js:3:1

根据url加载模块,使用的是webworker全局环境下的importScripts方法

function requestFromWebWorker(url, callback, charset) {
    // Load with importScripts
    var error;
    try {
      importScripts(url);
    } catch (e) {
      error = e;
    }
    callback(error);
  }
  // For Developers
  seajs.request = requestFromWebWorker;

浏览器js线程中异步加载模块文件

  // 通过script标签加载脚本
  function request(url, callback, charset) {
    var node = doc.createElement("script")

    if (charset) {
      var cs = isFunction(charset) ? charset(url) : charset
      if (cs) {
        node.charset = cs
      }
    }

    addOnload(node, callback, url)

    node.async = true
    node.src = url

    // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
    // the end of the insert execution, so use `currentlyAddingScript` to
    // hold current node, for deriving url in `define` call
    currentlyAddingScript = node

    // ref: #185 & http://dev.jquery.com/ticket/2709
    baseElement ?
        head.insertBefore(node, baseElement) :
        head.appendChild(node)

    currentlyAddingScript = null
  }
  //添加加载完成之后的处理,包括报错、清除对象、移除dom等操作
  function addOnload(node, callback, url) {
    var supportOnload = "onload" in node

    if (supportOnload) {
      node.onload = onload
      node.onerror = function() {
        emit("error", { uri: url, node: node })
        onload(true)
      }
    }
    else {
      node.onreadystatechange = function() {
        if (/loaded|complete/.test(node.readyState)) {
          onload()
        }
      }
    }

    function onload(error) {
      // Ensure only run once and handle memory leak in IE
      node.onload = node.onerror = node.onreadystatechange = null

      // Remove the script to reduce memory leak
      // 添加了又去除掉
      if (!data.debug) {
        head.removeChild(node)
      }

      // Dereference the node
      node = null

      callback(error)
    }
  }

  // For Developers
  seajs.request = request

核心模块类 Module

Module类定义

//定义module类
function Module(uri, deps) {
  //模块路径
  this.uri = uri
  //这是一个字符串数组,内容是该模块依赖模块的id列表
  this.dependencies = deps || []
  //这是该模块所依赖的模块的一个map key为id,value为Module对象
  this.deps = {} // Ref the dependence modules
  //模块状态
  this.status = 0
  //用来辅助load的一个数组,load完成后会删掉
  this._entry = []
}

 

模块缓存

var cachedMods = seajs.cache = {}

原型方法列表

// 获取模块中依赖模块的uri数组
Module.prototype.resolve 
// 一个辅助模块load过程的函数
Module.prototype.pass
//加载并执行模块
Module.prototype.load
//模块加载完成后触发
Module.prototype.onload
//模块404时候触发
Module.prototype.error
//执行模块
Module.prototype.exec
//用来获取模块文件,每调用一次给一个缓存对象设置一个key value,value是一个函数,调用即开始加载文件

函数方法列表

//通过id获取文件uri
Module.resolve = function(id, refUri)
//用来定义一个模块
Module.define= function (id, deps, factory)
//将id、依赖、 factory 、模块加载状态设置给缓存中的模块
Module.save= function(uri, meta)
////根据uri,从缓存中获取模块,或者以接收的uri和deps参数创建一个模块返回,并加入缓存
Module.get=function(uri, deps)
//用来加载并运行模块
Module.use = function(ids, callback, uri)

暴露出来的API

 1 // Public API
 2 
 3 seajs.use = function(ids, callback) {
 4   //use 实际上创建了一个id为data.cwd + "_use_" + cid()的模块,这个模块的依赖模块是待启动的模块
 5   Module.use(ids, callback, data.cwd + "_use_" + cid())
 6   return seajs
 7 }
 8 
 9 Module.define.cmd = {}
10 global.define = Module.define
11 
12 
13 // For Developers
14 
15 seajs.Module = Module
16 data.fetchedList = fetchedList
17 data.cid = cid
18 
19 seajs.require = function(id) {
20   var mod = Module.get(Module.resolve(id))
21   if (mod.status < STATUS.EXECUTING) {
22     mod.onload()
23     mod.exec()
24   }
25   return mod.exports
26 }
27 
28 /**
29  * config.js - The configuration for the loader
30  */
31 
32 // The root path to use for id2uri parsing
33 data.base = loaderDir
34 
35 // The loader directory
36 data.dir = loaderDir
37 
38 // The loader's full path
39 data.loader = loaderPath
40 
41 // The current working directory
42 data.cwd = cwd
43 
44 // The charset for requesting files
45 data.charset = "utf-8"
46 
47 // data.alias - An object containing shorthands of module id
48 // data.paths - An object containing path shorthands in module id
49 // data.vars - The {xxx} variables in module id
50 // data.map - An array containing rules to map module uri
51 // data.debug - Debug mode. The default value is false
52 
53 seajs.config = function(configData) {
54 
55   for (var key in configData) {
56     var curr = configData[key]
57     var prev = data[key]
58 
59     // Merge object config such as alias, vars
60     if (prev && isObject(prev)) {
61       for (var k in curr) {
62         prev[k] = curr[k]
63       }
64     }
65     else {
66       // Concat array config such as map
67       if (isArray(prev)) {
68         curr = prev.concat(curr)
69       }
70       // Make sure that `data.base` is an absolute path
71       else if (key === "base") {
72         // Make sure end with "/"
73         if (curr.slice(-1) !== "/") {
74           curr += "/"
75         }
76         curr = addBase(curr)
77       }
78 
79       // Set config
80       data[key] = curr
81     }
82   }
83 
84   emit("config", configData)
85   return seajs
86 }
View Code

相关文章:

  • 2021-06-05
  • 2021-10-03
  • 2021-07-16
  • 2021-06-23
  • 2021-09-16
  • 2021-09-08
  • 2021-05-26
  • 2021-10-26
猜你喜欢
  • 2021-11-12
  • 2021-09-09
  • 2021-08-03
  • 2021-08-21
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案