Redux 中間件源碼清源

網上的Redux中間件原理解釋多有疏漏,譬如我在多篇blog上看到Redux中間件解釋以及Redux中間件深刻淺出(譯文)前文解釋的時候提到了chain,這其實很不許確,由於在applyMiddleWare內部不是按照Chainable call的邏輯實現的,很容易讓人誤會爲middleware1.middleware2...這種錯誤的邏輯,下文會根據源碼進行更正。後者,雖然調用邏輯將的大體對了,可是關於curry function不恰當的引入真的是大大的誤導,由於按照curry的邏輯,調用順序和實際源碼中的徹底是兩個不一樣方向。web

上面提到的緣起就是我更正的點和踩過的坑。關於middleware內部實現的fn組合和調用順序的闡述,我湊巧今天早上看到一篇知乎專欄文章Redux middleware 詳解,你們能夠看,這位兄弟解釋的過程和我debug獲得的結果是一致的,我也再也不贅述。下面,講一講,很怪的一個約定,爲何middleware都得習慣性最後redux

return next(action)api

以及爲什麼applyMiddleWare內部必須websocket

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

這樣才能鏈接action 和 reducersocket

Q1ui

針對末尾的return,我只能說這真的只是習慣,由於,你能夠在官方的例子real-world中修改api.js和thunk內部的實現,去掉最後的return.這是能夠的,爲何呢?緣由和Q2有重要關係。由於在Q2的最後enhancer就是經過store.dispatch講前面處理過的action分發給了reducer。可是,注意這裏有一個細節差異,那就是這種處理不是filter chain模式的逐步修改action獲得的,而是將action帶有的反作用在中間件內部實現消化。換言之,每個middleware都不是後一個或者前一個的return值提供者。spa

僅僅是每一個人都處理本身感興趣的部分,可是都不能修改action,同時根據須要調用next(action)將整個chain繼續下去,固然,若是你以爲在某一步出錯不用後續處理了,就能夠不掉用。debug

最後,說一點,全部的dispatch的掉用發端必定是store.dispatch(也就是已經compose(f1,f2,f3..store.orgin_dispatch)),這一步不該該產生返回值,不然我要reducer幹嗎。設計

Q2 爲什麼最後仍是得有原生的store.dispatch,這實際上是廢話沒有這個就無法進行reducer通知合併action更新state了。

基於上面的論述,咱們能夠肯定兩件事情。 第一,middleware中承載的邏輯應該定位爲反作用操做,而且不得修改action(可是能夠skip)。請記住,不要亂套fp的概念,這個不是monad,自己也不是f1(f2..(..)). 下面的是標準的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 ``

然而,在真實的redux裏面倒是

| f1                          | 

|  step process  1     | 

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

|   step process 2      |

|                  |f2 | | ... | 

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

 f1內部先作預處理,而後決定是否call f2,f2內部重複這個過程。

## 2016-5-12更新

第二,middleware中的return next(action) 更準確的應該是 let ret = next(action) -- 官網demo裏面 return ret -- 徹底沒必要要 由於 你能夠推理 也能夠 寫console.log加斷點跟蹤,這些return 最後給誰了? 答案是 store.dispatch(這裏的dispatch就是你上面 applyMiddleware加強之後的)。因此,明白了吧,這就是一個常規的嵌套調用,mid1裏面 next-》mid2 next->mid3-> ... 這樣來的最後的 next(中間件最後)其實 就是 store原生的 dispatch 到這裏 咱們的action終於給了 reducer。

第三,經過上面的闡述,我能夠給一個本身的結論,那就是middleware的設計定位應該是處理和業務無關的反作用操做(好比 websocket,http,db,log等等),且它也一樣適合作 filter(不合法的action我不傳遞了) 和  interceptor(action 加強好比,你穿入user,我附加上user的擴展信息,而後next給後面)

相關文章
相關標籤/搜索