博客 知否知否,Redux源码竟如此意味深长(下集)

知否知否,Redux源码竟如此意味深长(下集)

   包袋鼠   发表于 2021-11-25 17:06  250  0

牵动14亿国人心弦的春节假期结束了

是不是还意犹未尽?!

胡吃海喝日夜颠倒

起不来床又心里发慌

……


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/569ecbe14b1ece77f54c66a7b9e5a2e8..jpg


emmmmmmmm...

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/592e0dbf2471d88296c787f74137427a..jpg


放纵之后留下的不止有悔恨,还有焦虑

又要上班啦

新的一年

需要更努力的工作才能做到足够优秀呀


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/16e843668572fdec7100d71a60713709..jpg

几乎同样的剧情,几乎每年都要重演一遍?

莫慌莫慌

#技本功#又回来啦!

好好学习

天天向上

2019 努力成为锦鲤体质,做锦鲤本鲤!

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/8f3250c28564169ea696561fba601c9d..jpg


-2019年第6期-


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/ebf7076042118d62293c7f1e6a806251..jpg

本期夫子:长卿

袋鼠云 前端开发工程师


上集回顾


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

 

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/1b069b416655c1ad239a99a5f96766e6..jpg


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


1. action的结构是如何的?

2. 如何去定义一个reducer?

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

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

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

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

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


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

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/6c06f8cfe8998d2a0ebb3e97fe45bd34..jpg


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


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/053c6141bf3aabf638759f28554aab22..jpg


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/418c9594921ca3c05ad121160104b47a..jpg


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/702b9a76add7614f8600469301ce2f10..jpg


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


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/7a5178c53bf68b7d97d0437ba94776f0..jpg


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


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/c0a3068fb3481107f0f8fd15bfd9f95b..jpg


函数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是如何监听状态发生改变的?


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/bf7adc54914541c9eb257a9c81575824..jpg


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

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

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

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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/cc3320739ec8ce01c00895a38c5ffe46..jpg


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


data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/c8fbfdb27cd063fab98e641c860ea7f3..jpeg


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


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

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

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


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


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


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/25140902cdebfc64451f7e3f335c4e6d..jpg


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



看完是不是已满腔热血

充满了斗志


       来来来~http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user9/article/b8f6fdce223c26cced588d8522b5acbd..jpg

有用的文章总是需要多读几遍

0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群