我是Redux的新手,正在学习如何为React应用程序创建中间件。我想问一个关于将自定义中间件创建为CURRIED函数的问题,那就是为什么会出现问题?在创建中间件的情况下,currying有什么好处?也就是说,为什么不写const middleware = store=>next=>action=>{}
而不写const middleware = (store,next,action)=>{}
。
答案 0 :(得分:0)
为什么要咖喱
实际上,Currying尝试将程序状态的更改次数减至最少 通过使用不可变数据和纯(无副作用)函数而称为副作用。当您要编写可轻松重用和配置的少量代码模块时,避免在部分应用程序中频繁调用具有相同参数的函数,则Currying很有帮助。
在中间件环境中进行curring的好处
通过使用currying,redux基本上为您提供了三个钩子函数:
const firstFunction = logger(store)
const secondFunction = firstFunction(next)
const thirdFunction = secondFunction(action)
现在,根据不同的情况,以上每个功能都有其自己的用途。 Store是在第一个功能中创建的,而第二个功能则为您提供了下一个中间件,而在第三个功能中,我们可以使用前一个中间件的结果操作来进行某些操作。
Redux的共同作者Dan Abramov也回答了这个问题。您可以检查他对此here
的想法答案 1 :(得分:0)
这是因为compose的工作原理。
假设我有2个功能:plus2和times3,那么我可以将它们组合为:
const plus2Times3 = compose(plus2,times3);
plus2Times3(1);//(1+2)*3=9
plus2Times3(2);//(2+2)*3=12
comp2对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
。这意味着redux可以使用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)
Here是一个自写的redux与react-redux结合使用的示例,展示了如何使用compose从一系列中间件函数中创建一个函数。
以下代码演示了如何轻松地构成中间件功能:
//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});
答案 2 :(得分:-1)
好的,我会尽力澄清您的困惑。 首先,我们了解中间件的目的
中间件是一些代码,您可以在接收代码的框架之间放置 请求,并生成响应的框架
由于currying允许您从另一个函数返回一个函数,因此您可以通过这种方式看到它,在将某些内容提取到框架之前,我们希望执行一些其他操作,因此,如您所建议的那样,您可以这样做>
const middleware = (store,next,action)=>{}
我们直接调用框架代码,使用currying可以中断并完成我们的工作
希望有帮助