在使用redux的過程當中,難免要用到中間件,用到中間件,就免不了使用compose方法來解決中間件層層嵌套的問題,那麼redux中的compose方法實現原來是怎樣的呢?javascript
compose(...functions)java
這是函數式編程中的方法,爲了方便,被放到了 Redux 裏。 當須要把多個 store 加強器(中間件) 依次執行的時候,須要用到它。編程
(arguments): 須要合成的多個函數。預計每一個函數都接收一個參數。它的返回值將做爲一個參數提供給它左邊的函數,以此類推。例外是最右邊的參數能夠接受多個參數,由於它將爲由此產生的函數提供簽名。(譯者注:compose(funcA, funcB, funcC) 形象爲 compose(funcA(funcB(funcC()))))redux
(Function): 從右到左把接收到的函數合成後的最終函數。函數式編程
import {componse} from 'redux'
function add1(str) {
return 1 + str;
}
function add2(str) {
return 2 + str;
}
function sum(a, b) {
return a + b;
}
let str = compose(add1,add2,add3)('x','y')
console.log(str)
//輸出結果 '12xy'
複製代碼
上面代碼compose(add1,add2,add3)('x','y')方法實際上等同於下面的代碼函數
add1(add2(add3('x','y')))
複製代碼
一步步解析compose方法內部的實現,首先從用法compose(add1,add2,add3)('x','y')來看,compose方法的運行結果顯然返回的是一個函數.ui
function compose(...fns){
return function(...args){ // args => ['x','y']
...處理代碼
}
}
複製代碼
因爲只有最右邊的中間件才能接受多個參數,咱們先將它取出來,將多個的參數單獨傳給他 其餘的中間件函數都只有一個參數,就是他右側中間件函數執行以後的返回值編碼
function compose(...fns){
return function(...args){ // args => ['x','y']
let last = fns.pop(); // sum
fns.reduceRight((val,fn)=>{
return fn(val)
},last(...args))
}
}
複製代碼
咱們來分析一下 fns.reduceRight中的運行spa
fns.reduceRight((val,fn)=>{
return fn(val)
},last(...args))
複製代碼
第一次 val 爲 sum('x','y') fn爲 add2code
第二次 val 爲 add2(sum('x','y')) fn 爲 add1
運行結束 返回 add1(add2(sum('x','y')));
這樣,compose的運行原理就基本解釋清楚了,可是,這個只是redux中compose方法之前的實現方法.如今redux中對於compose的實現換了一種更加優雅的方法
它摒棄了原來將最後一箇中間件函數提取出來的方法,直接一行代碼將內部邏輯實現了
function compose(...fns){
return fns.reduce((a,b)=>(...args)=>a(b(...args)))
}
複製代碼
咱們仍是以compose(add1,add2,sum)('x','y')爲例對fns.reduce進行解析
fns.reduce((a,b)=>(...args)=>a(b(...args)))
//展開
function compose(...fns){
return fns.reduce((a,b)=>{
return (...args)=>{
return a(b(...args))
}
}
}
})
//第一次 運行 a爲add1 b爲add2
//第二次 運行 a爲 (...args)=>{
return add1(add2(...args))
}
b爲 sum
//運行結束 返回
(...args)=>{
return ((...args)=>{
return add1(add2(...args))
})(sum(...args))
}
//爲了能更好的區分邏輯,我把這裏稍微改一下
(...args2)=>{
return ((...args)=>{
return add1(add2(...args))
})(sum(...args))
}
//等價於
(...args2)=>{
add1(add2(sum(...args2)))
}
//args2替換爲['x','y']
add1(add2(sum('x','y')))
複製代碼
邏輯總算是理清楚了,真的是有夠繞的
每次源碼閱讀與解析,老是可以在不經意的角落發現使人讚歎的代碼,編程的魅力大概就在這裏吧
若是以爲還能夠,能在諸君的編碼之路上帶來一點幫助,請點贊鼓勵一下,謝謝!