Redux 中間件源碼清源

網(wǎng)上的Redux中間件原理解釋多有疏漏百匆,譬如我在多篇blog上看到Redux中間件解釋以及Redux中間件深入淺出(譯文)前文解釋的時(shí)候提到了chain潘拨,這其實(shí)很不準(zhǔn)確非迹,因?yàn)樵赼pplyMiddleWare內(nèi)部不是按照Chainable call的邏輯實(shí)現(xiàn)的惩歉,很容易讓人誤會為middleware1.middleware2...這種錯誤的邏輯抡谐,下文會根據(jù)源碼進(jìn)行更正裁奇。后者,雖然調(diào)用邏輯將的大致對了麦撵,但是關(guān)于curry function不恰當(dāng)?shù)囊胝娴氖谴蟠蟮恼`導(dǎo)刽肠,因?yàn)榘凑誧urry的邏輯,調(diào)用順序和實(shí)際源碼中的完全是兩個(gè)不同方向免胃。

上面提到的緣起就是我更正的點(diǎn)和踩過的坑音五。關(guān)于middleware內(nèi)部實(shí)現(xiàn)的fn組合和調(diào)用順序的闡述,我湊巧今天早上看到一篇知乎專欄文章Redux middleware 詳解羔沙,大家可以看躺涝,這位兄弟解釋的過程和我debug得到的結(jié)果是一致的,我也不再贅述扼雏。下面坚嗜,講一講,很怪的一個(gè)約定呢蛤,為什么middleware都得習(xí)慣性最后

return next(action)

以及為何applyMiddleWare內(nèi)部必須

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

這樣才能連接action 和 reducer

Q1

針對末尾的return惶傻,我只能說這真的只是習(xí)慣,因?yàn)槠湔希憧梢栽诠俜降睦觬eal-world中修改api.js和thunk內(nèi)部的實(shí)現(xiàn)银室,去掉最后的return.這是可以的,為什么呢励翼?原因和Q2有重要關(guān)系蜈敢。因?yàn)樵赒2的最后enhancer就是通過store.dispatch講前面處理過的action分發(fā)給了reducer。但是汽抚,注意這里有一個(gè)細(xì)節(jié)差別抓狭,那就是這種處理不是filter chain模式的逐步修改action得到的,而是將action帶有的副作用在中間件內(nèi)部實(shí)現(xiàn)消化造烁。換言之否过,每一個(gè)middleware都不是后一個(gè)或者前一個(gè)的return值提供者午笛。

僅僅是每個(gè)人都處理自己感興趣的部分,但是都不能修改action苗桂,同時(shí)根據(jù)需要調(diào)用next(action)將整個(gè)chain繼續(xù)下去药磺,當(dāng)然,如果你覺得在某一步出錯不用后續(xù)處理了煤伟,就可以不掉用癌佩。

最后,說一點(diǎn)便锨,所有的dispatch的掉用發(fā)端一定是store.dispatch(也就是已經(jīng)compose(f1,f2,f3..store.orgin_dispatch)),這一步不應(yīng)該產(chǎn)生返回值围辙,否則我要reducer干嘛。

Q2 為何最后還是得有原生的store.dispatch,這其實(shí)是廢話沒有這個(gè)就沒法進(jìn)行reducer通知合并action更新state了放案。

基于上面的論述姚建,我們可以確定兩件事情。 第一,middleware中承載的邏輯應(yīng)該定位為副作用操作卿叽,并且不得修改action(但是可以skip)桥胞。請記住恳守,不要亂套fp的概念考婴,這個(gè)不是monad,本身也不是f1(f2..(..)). 下面的是標(biāo)準(zhǔn)的f1(f2..(..)) ``let f1 = (x) => { x = x + 1 ;return x + 1}

undefined

let f2 = (y) => (2 * y)

undefined

let f3 = (x) => f1(f2(x))

undefined

f3(2)

6 ``

然而催烘,在真實(shí)的redux里面卻是

| f1 ? ? ? ? ? ? ? ? ? ? ? ? ?|?

| ?step process ?1 ? ? |?

-------------------- => compose(f1,f2,f3..)?

| ? step process 2 ? ? ?|

| ? ? ? ? ? ? ? ? ?|f2 | | ... |?

|------------------|

?f1內(nèi)部先做預(yù)處理沥阱,然后決定是否call f2,f2內(nèi)部重復(fù)這個(gè)過程伊群。

## 2016-5-12更新

第二考杉,middleware中的return next(action) 更準(zhǔn)確的應(yīng)該是 let ret = next(action) -- 官網(wǎng)demo里面 return ret -- 完全不必要 因?yàn)?你可以推理 也可以 寫console.log加斷點(diǎn)跟蹤,這些return 最后給誰了舰始? 答案是 store.dispatch(這里的dispatch就是你上面 applyMiddleware增強(qiáng)以后的)崇棠。所以,明白了吧丸卷,這就是一個(gè)常規(guī)的嵌套調(diào)用枕稀,mid1里面 next-》mid2 next->mid3-> ... 這樣來的最后的 next(中間件最后)其實(shí) 就是 store原生的 dispatch 到這里 我們的action終于給了 reducer。

第三谜嫉,通過上面的闡述萎坷,我可以給一個(gè)自己的結(jié)論,那就是middleware的設(shè)計(jì)定位應(yīng)該是處理和業(yè)務(wù)無關(guān)的副作用操作(比如 websocket沐兰,http,db,log等等)哆档,且它也同樣適合做 filter(不合法的action我不傳遞了) 和? interceptor(action 增強(qiáng)比如,你穿入user住闯,我附加上user的擴(kuò)展信息瓜浸,然后next給后面)

## 2016-5-12 追加更新

剛剛同事問我上面說的對應(yīng)源代碼中的執(zhí)行細(xì)節(jié)澳淑,包括但不限于何時(shí)是參數(shù)綁定,何時(shí)是函數(shù)執(zhí)行插佛。我從他的問題里面漸漸意識到偶惠,原來

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朗涩,隨后出現(xiàn)的幾起案子忽孽,更是在濱河造成了極大的恐慌,老刑警劉巖谢床,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兄一,死亡現(xiàn)場離奇詭異,居然都是意外死亡识腿,警方通過查閱死者的電腦和手機(jī)出革,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渡讼,“玉大人骂束,你說我怎么就攤上這事〕审铮” “怎么了展箱?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹬昌。 經(jīng)常有香客問我混驰,道長,這世上最難降的妖魔是什么皂贩? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任栖榨,我火速辦了婚禮,結(jié)果婚禮上明刷,老公的妹妹穿的比我還像新娘婴栽。我一直安慰自己,他們只是感情好辈末,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布愚争。 她就那樣靜靜地躺著,像睡著了一般本冲。 火紅的嫁衣襯著肌膚如雪准脂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天檬洞,我揣著相機(jī)與錄音狸膏,去河邊找鬼。 笑死添怔,一個(gè)胖子當(dāng)著我的面吹牛湾戳,可吹牛的內(nèi)容都是我干的贤旷。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼砾脑,長吁一口氣:“原來是場噩夢啊……” “哼幼驶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起韧衣,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤盅藻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后畅铭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氏淑,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年硕噩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了假残。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炉擅,死狀恐怖辉懒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谍失,我是刑警寧澤眶俩,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站袱贮,受9級特大地震影響仿便,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攒巍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荒勇。 院中可真熱鬧柒莉,春花似錦、人聲如沸沽翔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仅偎。三九已至跨蟹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橘沥,已是汗流浹背窗轩。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留座咆,地道東北人痢艺。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓仓洼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親堤舒。 傳聞我的和親對象是個(gè)殘疾皇子色建,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 為什么dispatch需要middleware 上圖表達(dá)的是 redux 中一個(gè)簡單的同步數(shù)據(jù)流動的場景,點(diǎn)擊 b...
    一個(gè)胖子的我閱讀 1,996評論 1 9
  • 看到標(biāo)題舌缤,也許您會覺得奇怪箕戳,redux跟Koa以及Express并不是同一類別的框架,干嘛要拿來做類比国撵。盡管漂羊,例如...
    Perkin_閱讀 1,731評論 0 4
  • http://gaearon.github.io/redux/index.html ,文檔在 http://rac...
    jacobbubu閱讀 79,975評論 35 198
  • 學(xué)習(xí)必備要點(diǎn): 首先弄明白卸留,Redux在使用React開發(fā)應(yīng)用時(shí)走越,起到什么作用——狀態(tài)集中管理 弄清楚Redux是...
    賀賀v5閱讀 8,915評論 10 58
  • 前言 本文 有配套視頻,可以酌情觀看耻瑟。 文中內(nèi)容因各人理解不同旨指,可能會有所偏差,歡迎朋友們聯(lián)系我討論喳整。 文中所有內(nèi)...
    珍此良辰閱讀 11,909評論 23 111