jyzwf / codeanalysis Goto Github PK
View Code? Open in Web Editor NEW源码解读系列
源码解读系列
接下来是一些思考或者说是值得学习的地方
createStore.js
里面的一个函数 --> ensureCanMutateNextListeners
function ensureCanMutateNextListeners() {
// 判断 nextListeners 和 currentListeners 是同一个引用
if (nextListeners === currentListeners) {
// 通过数组的 slice 方法,复制出一个 listeners ,赋值给 nextListeners
nextListeners = currentListeners.slice()
}
}
为什么要出现这个函数呢??
这部分代码上面有几行英文注释大致讲述了原因,
当我们 dispatch
的时候,这时会先执行如下步骤:
const listeners = (currentListeners = nextListeners)
就是先将 nextListener 赋值给 currentListener 在赋值给 listener ,接着就是执行之前 subscribe 里面注册的监听器了,我们可以想象如下场景:
let unSubscribe1 = store.subscribe(() => {
let unSubscribe2 = store.subscribe(()=>{})
// 或者取消之前的一个订阅
})
在执行监听器的时候,里面又进行了订阅,那么,现在假设已经执行了前面订阅的监听函数,现在又取消了,或者又添加了新的订阅监听器,这样子就会出现不确定性和不知名的错误。所以,redux
统一将后面当前 listener
函数执行里面又订阅的 listener
安排到 下一轮
执行。
我们可以分析,当 listener
函数里面又进行 subscribe 时,会调用 ensureCanMutateNextListeners
,这时候,currentListeners = nextListeners
,会执行 if
,nextListeners
将拷贝 currentListeners
的副本,subscribe
订阅的 listener
函数就会被放进 nextListeners
,以便下一轮的执行,这样就不会影响到 currentListeners
,也就是本轮执行的 listeners 集合
。避免了错误
此文是自己对于阅读 Seajs
后的感悟,水平有限,如有不对或者不当,欢迎纠正 ^_^
CMD
对于前端来说耳熟能详,而它是 SeaJS
在推广过程中对模块定义的规范化产出,此前一直对模块化比较新奇和疑惑,但没有细细研究,现在借 SeaJS
来解开自己心中的疑惑,虽说现在 webpack
等工具的兴起使 Seajs
走向了没落,但学习里面的**还是很不错的
当然,本文并不会逐行分析,只是挑重点的来,重点就是 module.js
这个文件
我们以以下代码为开端
// 加载一个模块,在加载完成时,执行回调
seajs.use('./A', function(a) {
a.doSomething();
});
// A.js
define(function(require, exports, module) {
// 获取模块 B 的接口
var B = require('./B');
// 调用模块 B 的方法
B.doSomething();
//获取模块 C 的接口
var C = require('./C');
// 调用模块 C 的方法
C.doSomething();
module.exports = {
name: 'A',
doSomething: function() {};
};
});
// B.js
define(function(require, exports, module) {
// 获取模块 E 的接口
var E = require('./E');
// 调用模块 E 的方法
E.doSomething();
//获取模块 F 的接口
var F = require('./F');
// 调用模块 F 的方法
F.doSomething();
module.exports = {
name: 'B',
doSomething: function() {};
};
});
// E.js、F.js 、C.js 没有依赖,直接暴露接口
define(function(require, exports, module) {
// 对外提供接口
module.exports = {
name: 'x',
doSomething: function() {};
};
});
M 先会执行 load
方法去加载自己的依赖模块 A ,此时会把自己传给 A 的_entry数组
(在pass方法里 ),并将自己的 _entry数组清空,便于下面代码的判断
// If module has entries not be passed, call onload
// pass方法执行完成后,mod._entry存储被依赖的模块;当前模块加载完成时,执行被依赖模块的回调函数
// 执行时机为,当依赖模块加载完成后,onload事件发生时,调用该依赖模块的load方法,执行被依赖模块的回调
if (mod._entry.length) {
mod.onload()
return
}
然后此时 if
不成立,执行后面通过添加 script
标签来加载 A
模块 , A 模块加载的同时,会执行A模块里面的 define
函数,实例化该模块 (调用 save
函数),收集该模块的一些信息,如该模块依赖的模块,模块名,factory
函数
A 模块加载好后调用其 load 方法,继续去加载 B、C 模块,注意,他又会在自己的 pass 方法中把 M 模块传给依赖模块,后面依次重复上述过程。
当 C、E、F
每个模块执行 load
里的 pass
方法后,由于此时他们已经没有可以依赖的模块,他们 的 _entry
数组里面是最初的 M 模块,回到 load
方法,上面的 if
语句就会执行,调用 onload
方法
也就是说,M 模块会被一直向后传递,直到末尾模块
才停止,然后每个末尾模块加载好后会去判断是否所有的末尾模块都加载好了,如果是,就执行 M 模块的回调函数。
M 的回调函数会依次执行依赖模块的 exec
方法 ,把返回值按顺序传给回调函数使用。
回看每个模块的 exec
方法
这个方法就是将每个模块的 factory
函数进行执行,并将暴露的值返回出去。
总的来说,可以概括如下:
seajs 一开始就去加载各个模块,并在 define
中提取有用信息备用,然后,模块执行时 ,碰到require(‘xxx’),再去执行这个模块的 exec 方法,暴露结果供使用。
前面只是简单的讲了下 module
这个文件的流程,其中还有少可以学习的地方,还有其他文件,如 util-request.js
是创建script 标签来请求文件的,util-path.js
是用来分析路径的,util-deps.js
是用来分析依赖的,等等,都可以学到很多知识。
至此 seajs 就讲完了,欢迎交流 ^_^
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.