一:

1.本文是基于seajs2.2.1编写的,之后版本应该大同小异

2.本文仅代表个人观点,如有理解错误,敬请指出,大家一起学习

二:

1.首先放一张我画的流程图

这是我理解的seajs的基本的所有流程,接下来通过代码结合该流程图讲解下我的理解

2.1.首先从seajs.use开始,如以下图的代码所示

首先执行preload方法,看preload方法,其实就是执行module.use方法,所以我们直接从module.use讲起,先获取module,如果没有就新建,并且缓存在cachedMods中,定义callback方法(之后会讲),然后执行module.load方法(注意module.get方法,是把所有的ids当做deps传入的)

2.2.module.load方法

看代码,第一次进来,该模块的status还是0,第一个if判断主要是为了require同一个模块多次时只需加载一次(已经loading的只需等他自己的回调),然后resolve方法是用来解析路径的,emit该方法是用来触发seajs自己定义的事件的,seajs.on可以定义事件,这里会触发load事件(如果有自定义),之后的for循环是若主模块的依赖模块还没被加载,就在被依赖的模块的waiting数组中放入主模块的key值以及被依赖次数。当主模块的remain为0时,就加载自身代码,否则往下进入Module.prototype.fetch方法

2.3.Module.prototype.fetch

首先改变状态为fetch,fetchinglist和callbackList分别用来判断和缓存模块,把sendrequest方法存入requestCache返回回去(在sendrequest中有吧onrequest方法传了进去(待会会调用到)),然后module.load方法继续执行,看2.2的图最后一个for循环遍历所有依赖模块执行sendrequest.

module.status更新为FETCHING.

2.4.sendRequest(seajs.request) 以及addonload

执行request方法,创建一个节点,在该节点上加上一个onload方法,然后插入该节点,插入后会执行插入的代码,一般我们是这么写seajs的,如下

sea.use('a',function(){});       define(function(require,exports,module){var b require('b');   ...;})

所以插入会执行define的方法,define方法主要作用是更新deps和factory,他会根据正则匹配把所有require里面的内容提出来,找到绝对路径,再把factory缓存下来,便于之后执行。

(这里举个例子,如上面的代码,主模块a一开始的deps为他自身a,当a模块load进来,执行define函数,a的deps就更新为b了)

然后就执行addonload中的callback方法

2.5.onRequest--> module.load

见2.3的图,主要的作用是让他的子模块执行module.load方法,如果子模块也有依赖,则重复上述步骤,如果没有,则会进入Module.prototype.onload方法

module.status更新为SAVED-->module.status更新为LOADING

2.6.Module.prototype.onload

mod.callback是当只有使用seajs.use时定义的,可以认为只有主模块会执行,for循环写的是当被依赖的模块加载一次,主模块的remain就减去相应的数量,直至为0,主模块进入onload方法,由于主模块youcallback,执行mod.callback()

module.status更新为LOADED

2.7mod.callback()-->module.prototype.exec(部分见图2.1)

图2.1的图中可以看出,模块会先执行module.prototype.exec后会执行自定义的callback方法。

module.prototype.exec就是执行factory方法,也就是define时定义的方法,这里有几个方法,require方法主要作用是执行引进来的方法(已经在前面把他加载进来了,但是还未执行,执行factory时顺序执行require方法,被返回exports)

require.async异步加载,其本质就是module.use就是在执行时新建了一个模块(重走了上述步骤)

exports就是暴露出来的方法,到这里mod.status就变成status.executed了,到这里所有的就都结束了。

module.status更新为EXECUTING-->module.status更新为EXECUTED.

3.结语

有一些里面的方法及细节没有讲到,主要讲了大致流程,如果有错误,请帮忙指出及修改,谢谢!

seajs原理解析的更多相关文章

  1. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  2. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  3. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  4. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  5. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  6. alibaba-dexposed 原理解析

    alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...

  7. 支付宝Andfix 原理解析

    支付宝Andfix 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49802429 原理参考地址: http://blo ...

  8. JavaScript 模板引擎实现原理解析

    1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...

  9. Request 接收参数乱码原理解析三:实例分析

    通过前面两篇<Request 接收参数乱码原理解析一:服务器端解码原理>和<Request 接收参数乱码原理解析二:浏览器端编码原理>,了解了服务器和浏览器编码解码的原理,接下 ...

随机推荐

  1. wdcp/wdlinux 常用工具及命令集

    强制修改Mysql的root密码,在忘记mysql密码时有用 sh /www/Wdlinux/tools/mysql_root_chg.sh ftp配置文件检查,在FTP不能连接或登录时有用sh /w ...

  2. MemCached高级缓存

    MemCached高级缓存配置 Memcache相关介绍: memcache 是一个高性能的分布式的内存对象缓存系统,它能够存储各种各样的的数据,包括图片,视频,文件等等.缓存功能. DB.数据源-- ...

  3. wamp目录索引图片不显示

    在wampserver安装目录下  \bin\apache\Apache2.2.21\conf\extra\httpd-autoindex.conf Alias /icons/ "c:/Ap ...

  4. 转载自php100中文网 centos下lamp 环境搭建

    学习PHP脚本编程语言之前,必须先搭建并熟悉开发环境,开发环境有很多种,例如LAMP.WAMP.MAMP等.这里我介绍一下LAMP环境的搭建,即Linux.Apache.MySQL.PHP环境. 一. ...

  5. 转:VmWare下安装CentOS6图文安装教程

    文章来自于:http://www.cnblogs.com/seesea125/archive/2012/02/25/2368255.html 查看文章索引请通过http://www.cnblogs.c ...

  6. obj文件的连接问题以及tlib的基本用法

    1.基础研究 用tcc将程序编译为.obj文件. 这里也可以使用tcc -linclude run.c来将run.c文件编译成run.obj文件. 再用tcc对下面的程序进行编译链接,发现提示错误: ...

  7. 使用SQLiteDatabase进行数据库操作的步骤

    1.获取SQLiteDatabase对象,它代表了与数据库的连接.2.调用SQLiteDatabase的方法来执行SQL语句.3.操作SQL语句的执行结果,比如用SimpleCursorAdapter ...

  8. 【转】android使用File Explorer无法访问系统内部文件--不错

    原文网址:http://blog.csdn.net/yangqicong11/article/details/8747042 设备:Samsung GT-P3110 系统:Android 4.1.1 ...

  9. java并发6-小结

    为什么需要并发   并发其实是一种解耦合的策略,它帮助我们把做什么(目标)和什么时候做(时机)分开.这样做可以明显改进应用程序的吞吐量(获得更多的CPU调度时间)和结构(程序有多个部分在协同工作).做 ...

  10. HDU_1426——数独问题,DFS

    Problem Description 自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视. 据说,在2008北京奥运会上,会将数独列为一个单独的项目进行 ...