require源码分析之require

前言

通过上面的两篇文章,分析了require.js加载过程中所做的工作,实际上就是创建一个contextName为’_'对应的context上下文,也只到require函数实际上就是调用localRequire函数,该函数的大概代码如下:

// deps表示依赖列表, callback表示回调函数,errback表示处理错误的回调函数
function localRequire(deps, callback, errback) {
 // 相关处理代码
}

在函数会对依赖模块对应对象的创建、模块的加载以及其他相关工作,是整个require最核心的逻辑处理。

localRequire函数处理流程分析

通过阅读源码,分析localRequire函数的处理流程如下:
localRequire流程处理

从上面可知最核心的处理是如下代码:

context.nextTick(function () {
    intakeDefines();
    requireMod = getModule(makeModuleMap(null, relMap));
    requireMod.skipMap = options.skipMap;
    requireMod.init(deps, callback, errback, {enabled: true});
	checkLoaded();
});
  • intakeDefines函数的主要功能是将globalDefQueue的内容copy到defQueue中并且根据条件调用callGetMoudle
  • getMoudle:不言而喻,获取模块
  • makeModuleMap:绘制Module依赖map
  • requireMod.init:module对象的init方法
  • checkLoaded:检查是否加载成功

本次创建了a.js和b.js两个js文件作为模块,在c.js中require中作为依赖,来分析整个流程相关的事情。

require(['./a.js', './b.js'], function(a, b) {
});

当加载c.js就会调用require函数,下面就具体分析下上面几个函数所做的事情。

在require.js加载过程中两次调用了req函数,所以两次定义了定时器,下面是req({}) context.nextTick中函数执行的过程,如下:
核心代码处理

可以看出实际上该函数直接调用了4个函数来处理相关逻辑:

  • makeModuleMap
  • getModule
  • module对象的init函数
  • checkLoaded函数

从上面可知:

  • req({})创建了模块id为_@r2,url为./_@r2.js
  • 分析可知req(cfg)创建了模块id为_@r3,url为./_@r3.js
  • require([‘a.js’,‘b.js’])创建了id为_@r4的模块,url为./_@r4.js其depMaps是a和b两个模块

实际上require([‘a.js’,‘b.js’])的过程与req({})中上图过程差不多,出现差别的地方是:

  • 调用module对象的init时,depMaps = [‘a’,‘b’],对depMaps进行遍历,对其中每一个依赖执行makeModuleMap操作,创建id为a和b的模块并将其存入registry中

然后就是列表a和b依次执行下面这四个函数:

  • makeModuleMap
  • getModule
  • module对象的init函数
  • checkLoaded函数

在流程中调用check函数的时候调用了有了较大的差别:

  • 首先在check函数中调用了fetch函数
  • 在fetch函数中调用了load函数
  • 在load函数中调用了req.load函数,而req.load函数是用于创建script节点,并设置srcipt中一些属性的,设置了async = true,这是异步加载的本质

同理模块b的过程也是如此,自此,默认明白了require是任何处理依赖列表,并且如何异步加载js文件的。

总结

通过对于源码的阅读分析,知道核心代码直接调用了下面四个函数:

  • makeModuleMap:构建ModuleMap的
  • getModule:获取module对象
  • module对象的init函数:设置deps,判断模块是否可使用以及依赖列表的中每个依赖的处理
  • checkLoaded函数:处理循环依赖等问题

require函数会通过上面四个函数创建模块,而require中依赖也是通过上面四个函数创建被加载的,这部分的主要实现是check函数中对于depMaps的遍历处理。

已经知道了require.js是如何处理依赖列表和加载依赖的,但是对于循环依赖是如何处理的,之后会看看require.js是如何处理循环依赖的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值