Redux API compose
2017-09-04 本文已影响39人
誑逩蝸犇
前言
在compose里面调用了Array.prototype.reduce方法,首先来分析一下这个方法的作用,详细可以查看reduce文档;
reduce
reduce方法,是从左向右,对数组中的每个元素按照传入回调函数和初始值进行运算;举个栗子:
let arr = [1,2,3,4,5];
let result = arr.reduce((a,b)=>{
return a+b;
});
console.log(result);
这个栗子最终会输出
15
即相当于做了以下的运算:
((((1+2)+3)+4)+5)
即相当于;
let arr = [1,2,3,4,5];
let add = (a,b)=>{
console.log(`${a}+${b}=`,a + b);
return a+b;
}
let result = arr.reduce((a,b)=>{
return add(a,b);
});
console.log(result);
有意思的事情
下面来看一个模拟redux插件的实现方式
let mynext = function(action){
console.log(action);
}
let wrapper0 = next=>action=>{
console.log('before');
let result = next(action);
console.log('after');
return result;
}
let wrapper1 = next=>action=>{
console.log('w1 before');
let result = next(action);
console.log('w1 after');
return result;
}
let wrapper2 = next=>action=>{
console.log('w2 before');
let result = next(action);
console.log('w2 after');
return result;
}
let result = compose(wrapper0,wrapper1,wrapper2);
console.log(result(mynext)('hello'));
最终输出结果
compose.png看到结果是不是很惊讶,这个就类似redux的中间件调用过程了,中间的是原始的store.dispatch,外面是各个插件wrapper2 ... 等的输出结果。其实这就是redux实现插件的内部机制。
compose源码解析
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
以上是ES6的源码,在redux的lib文件夹下,有一份编译好的ES5的源码,如下
function compose() {
for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
if (funcs.length === 0) {
return function (arg) {
return arg;
};
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(function (a, b) {
return function () {
return a(b.apply(undefined, arguments));
};
});
}
来看一下compose做了什么事情:
- 将arguments转化为数组;
- 在数组上,调用reduce方法,数组的内部是function,并且最终返回一个function;