作有追求的coder - Redux進階compose方法的實現與解析

前言

在使用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的實現換了一種更加優雅的方法

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')))
複製代碼

邏輯總算是理清楚了,真的是有夠繞的

結語

每次源碼閱讀與解析,老是可以在不經意的角落發現使人讚歎的代碼,編程的魅力大概就在這裏吧

若是以爲還能夠,能在諸君的編碼之路上帶來一點幫助,請點贊鼓勵一下,謝謝!

相關文章
相關標籤/搜索