上集回顾

Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用)

如果有小伙伴对这段代码不是很理解的话,建议先去学习Redux的使用再来看这篇源码,这样更加事半功倍。通过上段代码,我们拆分几个比较核心的点,我一一列举一下:

1. action的结构是如何的?

2. 如何去定义一个reducer?

3. combineReducers是如何整合多个reducer的?

4. createStore是如何创建一个store?

5.dispatch拿到action到底干了什么?

6. subscribe是如何监听状态发生改变的?

7. getState是如何拿到所有的状态值的?

上期我们先解决了前三个疑问,这期我们一起来探索后4个问题。

4、createStore是如何创建一个store?

首先我们先撸一个createStore架构出来:

通过这段代码我们知道了传参应该是什么样子和返回了什么。从中我发现了一个问题,createStore接受的是三个参数:1、reducer 2、预加载的state 3、redux-thunk之类的增强器。但是我们平时经常会写成如下这个样子:

我们会在第二个参数就传入了增强器,这跟源代码的参数结构不符哎,但是为什么就可以这么用了。接下来我们就看一下,reducer是如何做这个处理的。

当第二个参数preloadedState的类型是Function的时候,并且第三个参数enhancer未定义的时候,此时preloadedState将会被赋值给enhancer,preloadedState会替代enhancer变成undefined的。有了这么一层转换之后,我们就可以大胆地第二个参数传enhancer了。

解决了这个疑问之后,往下就是解释一下他返回的值是什么东西,这些解答我们就放在下面做解释,这里就不做赘述了。不过在接下去之前,我们得搞清楚下面这组变量代表啥意思。

其中变量isDispatching,作为锁来用,我们redux是一个统一管理状态容器,它要保证数据的一致性,所以同一个时间里,只能做一次数据修改,如果两个action同时触发reducer对同一数据的修改,那么将会带来巨大的灾难。所以变量isDispatching就是为了防止这一点而存在的。

5、dispatch拿到action到底干了啥?

函数dispatch在函数体一开始就进行了三次条件判断,分别是以下三个:

1.判断action是否为简单对象

2.判断action.type是否存在

3. 判断当前是否有执行其他的reducer操作

当前三个预置条件判断都成立时,才会执行后续操作,否则抛出异常。在执行reducer的操作的时候用到了try-finally,可能大家平时try-catch用的比较多,这个用到的还是比较少。执行前isDispatching设置为true,阻止后续的action进来触发reducer操作,得到的state值赋值给currentState,完成之后再finally里将isDispatching再改为false,允许后续的action进来触发reducer操作。接着一一通知订阅者做数据更新,不传入任何参数。最后返回当前的action。

6、subscribe是如何监听状态发生改变的?

在注册订阅者之前,做了两个条件判断:

1. 判断监听者是否为函数

2.  是否有reducer正在进行数据修改(保证数据的一致性)

接下来执行了函数ensureCanMutateNextListeners,下面我们看一下ensureCanMutateNextListeners函数的具体实现逻辑:

逻辑很简单,判断nextListeners和currentListeners是否为同一个引用,还记得初始变量定义那以及函数dispatch内部那两处的代码吗?

这两处将nextListeners和currentListeners引用了同一个数组,而ensureCanMutateNextListeners就是用来判断这种情况的,当nextListeners和currentListeners为同一个引用时,则做一层浅拷贝,这里用的就是Array.prototype.slice方法,该方法会返回一个新的数组,这样就可以达到浅拷贝的效果。

函数ensureCanMutateNextListeners作为处理之后,将新的订阅者加入nextListeners中,并且返回取消订阅的函数unsubscribe。函数unsubscribe执行时,也会执行两个条件判断:

1. 是否已经取消订阅(已取消的不必执行)

2. 是否有reducer正在进行数据修改(保证数据的一致性)

通过条件判断之后,将该订阅者从nextListeners中删除。看到这里可能有小伙伴们对currentListeners和nextListeners有这么一个疑问?函数dispatch里面将二者引用同一个数组,为啥这里将二者分别引用两个值相同的数组?直接用currentListeners不可以吗?这里这样做其实也是为了数据的一致性,因为有这么一种的情况存在。当redux在通知所有订阅者的时候,此时又有一个新的订阅者加进来了。如果只用currentListeners的话,当新的订阅者插进来的时候,就会打乱原有的顺序,从而引发一些严重的问题。

7、getState是如何拿到所有的状态值的?

getState相比较dispatch要简单许多,返回currentState即可,而这个currentState在每次dispatch得时候都会得到响应的更新。同样是为了保证数据的一致性,当在reducer操作的时候,是不可以读取当前的state值的。

看完是不是已满腔热血

充满了斗志?

技本功丨知否知否,Redux源码竟如此意味深长(下集)的更多相关文章

  1. 技本功丨知否知否,Redux源码竟如此意味深长(上集)

    夫 子 说 元月二号欠下袋鼠云技术公号一篇关于Redux源码解读的文章,转眼月底,期间常被“债主”上门催债.由于年底项目工期比较紧,于是债务就这样被利滚利.但是好在这段时间有点闲暇,于是赶紧把这篇文章 ...

  2. 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)

    2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的“圣杯战争“.网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀... 所以,请珍惜以下 ...

  3. 技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列

    本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取 货真价值的才貌双全,别人家的孩子 高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零, ...

  4. 基于MVVM的知乎日报应用安卓源码

    使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP运行效果: <ignore_js_op> 使用说明: 项目结构 a ...

  5. 第三方知乎专栏应用Android源码

    这是一个国内开发者白瓦力贡献的一个简约的第三方知乎客户端,也许完整度不太高,但感觉还是相当不错的,其实我也是一个知乎迷,尽管平时围观的比较多. 我相信很多搞安卓开发的童鞋也去过知乎解惑吧.引用作者的描 ...

  6. 技本功丨利用 Atomic 构建 React 项目工作流,so easy!

    近日刷微博,#2018年结婚率创新低#荣登热门话题NO.1,沪浙最不积极. 生活压力越大,缺爱的人也越来越多...据本萌的不完全观察,程序猿虽然是压力加成的职业,在袋鼠云还是有不少早早脱了单.至于,脱 ...

  7. 技本功丨用短平快的方式告诉你:Flink-SQL的扩展实现

    2019年1月28日,阿里云宣布开源“计算王牌”实时计算平台Blink回馈给ApacheFlink社区.官方称,计算延迟已经降到毫秒级,也就是你在浏览网页的时候,眨了一下眼睛,淘宝.天猫处理的信息已经 ...

  8. 知乎日报客户端应用ios源码

    swift开发的知乎日报客户端详细源码,里面分UI和网络两个模块. 1.涉及到了大部分的UI控件的使用(甚至包括UIRefreshView,UITableConrol等等)2.Connection完成 ...

  9. Android扫码二维码、美女瀑布流、知乎网易音乐、动画源码等

    Android精选源码 QRCode 扫描二维码.扫描条形码.相册获取图片后识别.生...   一个简洁好看的loading弹窗   Android用瀑布流展示美女图片源码   Android知乎阅读 ...

随机推荐

  1. latex 字母上面加符号

    加^号 输入\hat  或 \widehat 加横线 输入 \overline 加波浪线 输入 \widetilde 加一个点 \dot{要加点的字母} 加两个点\ddot{要加点的字母} 加箭头 输 ...

  2. 『C++』Temp_2018_12_06

    #include <iostream> #include <string> using namespace std; class Type{ public: string Na ...

  3. 执行SQL查询导致磁盘耗尽故障演示

            a fellow in IMG wechat group 2 met an error about running out of disk space when using MySQL ...

  4. 常用的JavaScript设计模式(二)Factory(工厂)模式

    Factory通过提供一个通用的接口来创建对象,同时,我们还可以指定我们想要创建的对象实例的类型. 假设现在有一个汽车工厂VehicleFactory,支持创建Car和Truck类型的对象实例,现在需 ...

  5. Java软件开发者,如何学习大数据?

    正常来讲学习大数据之前都要做到以下几点 1.学习基础的编程语言(java,python) 2.掌握入门编程基础(linux操作,数据库操作.git操作) 3.学习大数据里面的各种框架(hadoop.h ...

  6. Python学习手册之捕获组和特殊匹配字符串

    在上一篇文章中,我们介绍了 Python 的字符类和对元字符进行了深入讲解,现在我们介绍 Python 的捕获组和特殊匹配字符串.查看上一篇文章请点击:https://www.cnblogs.com/ ...

  7. c语言程序设计:用strcpy比较数组(银行卡密码程序设计),strcpy(复制数组内容)和getchar()(敲键盘字符,统计不想要的字符的个数)

    统计从键盘输入一行字符的个数: 1 //用了getchar() 语句 2 //这里的\n表示回车 #include <stdio.h> #include <stdlib.h> ...

  8. ISAP学习笔记

    学完了ISAP,感觉心情舒畅,毕竟ISAP比Dinic好一点. 说到底ISAP其实是Dinic(不熟悉Dinic的人去我的博客找猴子课堂----最大流与最小割(看看思想),已经置顶)优化版,熟悉的人知 ...

  9. 【CF613D】Kingdom and its Cities(虚树,动态规划)

    [CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...

  10. 南京Uber优步司机奖励政策(12月14日到12月20日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...