前言
在使用redux的过程中,不免要用到中间件,用到中间件,就免不了使用compose方法来解决中间件层层嵌套的问题,那么redux中的compose方法实现原来是怎样的呢?
用法
compose(...functions)
这是函数式编程中的方法,为了方便,被放到了 Redux 里。 当需要把多个 store 增强器(中间件) 依次执行的时候,需要用到它。
参数
(arguments): 需要合成的多个函数。预计每个函数都接收一个参数。它的返回值将作为一个参数提供给它左边的函数,以此类推。例外是最右边的参数可以接受多个参数,因为它将为由此产生的函数提供签名。(译者注:compose(funcA, funcB, funcC) 形象为 compose(funcA(funcB(funcC()))))
返回值
(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方法的运行结果显然返回的是一个函数.
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中的运行
fns.reduceRight((val,fn)=>{
return fn(val)
},last(...args))
复制代码
第一次 val 为 sum('x','y') fn为 add2
第二次 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')))
复制代码
逻辑总算是理清楚了,真的是有够绕的
结语
每次源码阅读与解析,总是能够在不经意的角落发现令人赞叹的代码,编程的魅力大概就在这里吧
如果觉得还可以,能在诸君的编码之路上带来一点帮助,请点赞鼓励一下,谢谢!