Это из-за того, как compose работает.
Скажем, у меня есть 2 функции: plus2 и times3, тогда я могу сочинить их с помощью:
const plus2Times3 = compose(plus2,times3);
plus2Times3(1);//(1+2)*3=9
plus2Times3(2);//(2+2)*3=12
Что композитор сделалс plus2 и times3: (...arg)=>times3(...plus2(...arg))
Достаточно сложно разобраться с простыми функциями, но как насчет каррированных функций?
Все функции промежуточного программного обеспечения получают одно и то же состояние, поэтому, если у меня есть массив функций промежуточного программного обеспечения, я могу выполнить:
//middewares is [store=>next=>action=>next(action),store=>next=>action=>next(action)]
const mw = middlewares.map(fn=>fn({getState,dispatch}));
//mw is [next=>action=>next(action),next=>action=>next(action)]
Теперь у меня есть массив функций, которые next=>action=>next(action)
где следующийэто функция, которая выполняет действие.
Поэтому, если я предоставлю next=>action=>next(action)
следующую функцию, я получу функцию, которая будет следующей функцией: action=>does something
. Это означает, что при помощи редукса можно использовать compose для создания одной функции из массива функций:
const middeware = compose(middlewares.map(fn=>fn({getState,dispatch}));
//middeware is now next=>action=>do something
//redux can execute it with: middleware(reducer)(action)
Здесь - это пример самопишущего редукса в сочетании с реагировать-редуксом, который показывает, как составлятьиспользуется для создания одной функции из массива функций промежуточного программного обеспечения.
Вот код, демонстрирующий, как легко составлять функции промежуточного программного обеспечения:
//implementation of compose is very simple, I added taking
// out anything that isn't a function
const compose = (...functions) => {
return (
functions
//take out non functions
.filter(e => typeof e === 'function')
.reduce((result, fn) => {
return (...args) => result(fn(...args));
})
);
};
const middeWares = [
store => next => action => {
console.log('1', action);
next({ ...action, counter: action.counter + 1 });
},
store => next => action => {
console.log('2', action);
next({ ...action, counter: action.counter + 1 });
},
store => next => action => {
console.log('3', action);
next({ ...action, counter: action.counter + 1 });
},
];
//just pass in 88 as store, we don't use store
const middleWare = compose(...middeWares.map(x => x(88)));
//executing the middleware
//pass in id function as next function (probably reducer in redux)
middleWare(x=>x)({counter:86});
Redux мог бы выбрать любую сигнатуру для промежуточного ПО, если у него есть хранилище, следующее и действие. Следующий пример в основном такой же, как предыдущий, но отображает функции промежуточного программного обеспечения в нечто, что можно составить:
const compose = (...functions) => {
return (
functions
//take out non functions
.filter(e => typeof e === 'function')
.reduce((result, fn) => {
return (...args) => result(fn(...args));
})
);
};
//middleware could also have (action,next,store) signature
const middeWares = [
(action,next,store) => {
console.log('1', action);
next({ ...action, counter: action.counter + 1 });
},
(action,next,store) => {
console.log('2', action);
next({ ...action, counter: action.counter + 1 });
},
(action,next,store) => {
console.log('3', action);
next({ ...action, counter: action.counter + 1 });
},
];
//using 88 for store, we can map the middleware to s=>n=>a=>...
const middleWare = compose(...middeWares.map(x => n=>a=>x(a,n,88)));
//pass in id function as next function (could be dispatch or reducer)
// depending on how redux is written
middleWare(x=>x)({counter:86});