redux的applyMiddleware的第二部分細(xì)節(jié)

原文: redux的applyMiddleware細(xì)節(jié)分析

上篇文章中有提到中間件里有定義一個(gè)dispatch方法用來(lái)拋出異常,然后在middlewareAPI里調(diào)用的時(shí)候是攜帶參數(shù)了:

const middlewareAPI = {
   getState: store.getState, //獲取store里的state
   dispatch: (...args) => dispatch(...args) // 調(diào)用`dispatch`的時(shí)候會(huì)拋錯(cuò),如果在組合中間件之前調(diào)用,下面會(huì)說(shuō)
}

一開(kāi)始我以為是在調(diào)用的時(shí)候就會(huì)報(bào)錯(cuò),可是發(fā)現(xiàn)這個(gè)對(duì)象里的dispatch攜帶參數(shù),如果只是單純拋錯(cuò),完全可以不需要傳遞參數(shù),然后向下看下去才看到其中的奧妙。

到底奧妙在哪里,這段拋錯(cuò)代碼究竟是有什么作用。

先說(shuō)這段代碼的作用: 防止在對(duì)dispatch擴(kuò)展之前調(diào)用dispatch。

我們來(lái)寫個(gè)簡(jiǎn)單的middleware:

const exampleMiddle = ({getState, dispatch}) => next => action => {
    console.log('exampleMiddleware action is', action)
    return next(action) 
}

假設(shè)我們當(dāng)前并不知道那段dispatch函數(shù)拋出錯(cuò)誤的作用,我們可以根據(jù)applyMiddleware代碼來(lái)推算出來(lái)。

我們知道,在代碼里有對(duì)dispatch重新賦值操作:

dispatch = compose(...chain)(store.dispatch)

所以我們可以知道,在這個(gè)賦值之前調(diào)用的dispatch都是會(huì)拋錯(cuò)的(就是那段單純拋出錯(cuò)誤的dispatch函數(shù))。

所以為了證明這個(gè),我們來(lái)試下:

const exampleMiddle = ({getState, dispatch}) => next => {
  console.log('dispatch action', dispatch({}))
  return action => {
    console.log('exampleMiddleware action is', action)
    return next(action)
  }
}

然后你就會(huì)發(fā)現(xiàn)console里有錯(cuò)誤拋出,就是那段dispatchthrow

然后我們?cè)?code>dispatch = compose(...chain)(store.dispatch)之后再次調(diào)用dispatch,
也就是在最終觸發(fā)action的時(shí)候再調(diào)用,發(fā)現(xiàn)是可以調(diào)用(需要加判斷是否調(diào)用過(guò),否則就會(huì)死循環(huán)。后面解釋為啥死循環(huán)。)

會(huì)不會(huì)感覺(jué)不太對(duì),為啥在閉包作用域鏈外的更改會(huì)影響到閉包內(nèi)的變量?

先來(lái)證明,閉包內(nèi)的變量不受外部改變:

let name = 'first arg'
function run(firstArg){
  console.log('run params is', firstArg)
  return function next(){
    console.log('next params is', firstArg)
  } 
}
let next = run(name)
name = 'changed'
next() // next params is first arg

對(duì)吧,說(shuō)明外部的更改是不會(huì)影響到內(nèi)部的變量的。因?yàn)樽饔糜蜴溡呀?jīng)生成了。

我們?cè)賮?lái)看看另外一個(gè)情況:

let age = 99
let obj = {
  old: age,
  young: () => age
}
age = 18
obj.old // 99
obj.young() // 18

很明了了吧,因?yàn)槊看魏瘮?shù)調(diào)用的都是當(dāng)前作用域鏈的變量。如果對(duì)于這部分不理解,可以看這篇文章進(jìn)行深入了解。

可以發(fā)現(xiàn)我們自己寫的exampleMiddleware里,第一個(gè)參數(shù)里有傳入dispatch,然后返回的參數(shù)里攜帶了一個(gè)next參數(shù)(store.dispatch), 為什么還要傳遞dispatch, 并且dispatch也不可以在前面使用,只能在到action這步的時(shí)候才可以。所以為啥還要傳遞dispatch進(jìn)來(lái),直接傳遞了store.dispatch不是更好嗎? 這兩個(gè)不等價(jià),store.dispatch是原生的dispatch,所以可以直接返回,不會(huì)出現(xiàn)死循環(huán)。參數(shù)dispatch是組合中間件之后的dispatch,所以簡(jiǎn)單的直接調(diào)用會(huì)死循環(huán),會(huì)自己調(diào)用自己,所以需要判斷下。

總結(jié): middlewares通過(guò)compose組合這些中間件成一個(gè)鏈?zhǔn)降?code>dispatch,這樣每次dispatch都會(huì)運(yùn)行處理,可以發(fā)現(xiàn)dispatch源碼里,最后返回的是action。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,281評(píng)論 8 265
  • 一、什么情況需要redux? 1、用戶的使用方式復(fù)雜 2、不同身份的用戶有不同的使用方式(比如普通用戶和管...
    初晨的筆記閱讀 2,136評(píng)論 0 11
  • 為什么dispatch需要middleware 上圖表達(dá)的是 redux 中一個(gè)簡(jiǎn)單的同步數(shù)據(jù)流動(dòng)的場(chǎng)景,點(diǎn)擊 b...
    一個(gè)胖子的我閱讀 2,137評(píng)論 1 9
  • 學(xué)習(xí)必備要點(diǎn): 首先弄明白,Redux在使用React開(kāi)發(fā)應(yīng)用時(shí),起到什么作用——狀態(tài)集中管理 弄清楚Redux是...
    賀賀v5閱讀 9,078評(píng)論 10 58
  • http://gaearon.github.io/redux/index.html ,文檔在 http://rac...
    jacobbubu閱讀 80,431評(píng)論 35 198

友情鏈接更多精彩內(nèi)容