技本功丨知否知否,Redux源码竟如此意味深长(下集)
上集回顧
Redux是如何使用的?首先再來回顧一下這個使用demo(誰讓這段代碼完整地展示了redux的使用)
如果有小伙伴對這段代碼不是很理解的話,建議先去學習Redux的使用再來看這篇源碼,這樣更加事半功倍。通過上段代碼,我們拆分幾個比較核心的點,我一一列舉一下:
5.dispatch拿到action到底干了什么?
上期我們先解決了前三個疑問,這期我們一起來探索后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是否存在
當前三個預置條件判斷都成立時,才會執行后續操作,否則拋出異常。在執行reducer的操作的時候用到了try-finally,可能大家平時try-catch用的比較多,這個用到的還是比較少。執行前isDispatching設置為true,阻止后續的action進來觸發reducer操作,得到的state值賦值給currentState,完成之后再finally里將isDispatching再改為false,允許后續的action進來觸發reducer操作。接著一一通知訂閱者做數據更新,不傳入任何參數。最后返回當前的action。
6、subscribe是如何監聽狀態發生改變的?
在注冊訂閱者之前,做了兩個條件判斷:
接下來執行了函數ensureCanMutateNextListeners,下面我們看一下ensureCanMutateNextListeners函數的具體實現邏輯:
邏輯很簡單,判斷nextListeners和currentListeners是否為同一個引用,還記得初始變量定義那以及函數dispatch內部那兩處的代碼嗎?
這兩處將nextListeners和currentListeners引用了同一個數組,而ensureCanMutateNextListeners就是用來判斷這種情況的,當nextListeners和currentListeners為同一個引用時,則做一層淺拷貝,這里用的就是Array.prototype.slice方法,該方法會返回一個新的數組,這樣就可以達到淺拷貝的效果。
函數ensureCanMutateNextListeners作為處理之后,將新的訂閱者加入nextListeners中,并且返回取消訂閱的函數unsubscribe。函數unsubscribe執行時,也會執行兩個條件判斷:
通過條件判斷之后,將該訂閱者從nextListeners中刪除。看到這里可能有小伙伴們對currentListeners和nextListeners有這么一個疑問?函數dispatch里面將二者引用同一個數組,為啥這里將二者分別引用兩個值相同的數組?直接用currentListeners不可以嗎?這里這樣做其實也是為了數據的一致性,因為有這么一種的情況存在。當redux在通知所有訂閱者的時候,此時又有一個新的訂閱者加進來了。如果只用currentListeners的話,當新的訂閱者插進來的時候,就會打亂原有的順序,從而引發一些嚴重的問題。
7、getState是如何拿到所有的狀態值的?
getState相比較dispatch要簡單許多,返回currentState即可,而這個currentState在每次dispatch得時候都會得到響應的更新。同樣是為了保證數據的一致性,當在reducer操作的時候,是不可以讀取當前的state值的。
看完是不是已滿腔熱血
充滿了斗志?
總結
以上是生活随笔為你收集整理的技本功丨知否知否,Redux源码竟如此意味深长(下集)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#实现自动发送QQ消息
- 下一篇: Android加载/处理超大图片神器!S