柯里化是redux中间件实现洋葱模型的核心技术,通过store=>next=>action三层函数嵌套,依次注入store、链式next及action,在进入/退出时插入逻辑、修改或拦截action。

柯里化是 Redux 中间件实现洋葱模型控制流的核心技术。它不靠魔法,而是通过函数嵌套和闭包,把 store、next 和 action 逐层“注入”,让每个中间件既能访问状态,又能决定是否继续、修改或拦截 action。
柯里化三层结构对应洋葱的剥皮路径
每个中间件都写成三阶函数:
store => next => action => { ... }
这三步不是并列的,而是按顺序执行、层层包裹的:
- 第一层(store =>):在 applyMiddleware 初始化时调用,传入 store 实例,可安全使用
getState()或dispatch()(注意此时 dispatch 还未被增强) - 第二层(next =>):由上一个中间件传入,代表“下一个环节”的执行入口——可能是另一个中间件的最内层函数,也可能是原始的
store.dispatch - 第三层(action =>):真正响应 dispatch 调用的地方。只有这里拿到 action,才能做日志、异步、阻断、改写等操作
串联过程就是洋葱的“从外到内、再从内到外”
假设有三个中间件 logger、thunk、errorHandler,applyMiddleware 会这样组装:
macOS 微信消息自动化工具。通过 GUI 自动化实现:发送消息给指定联系人、读取聊天内容、监控新消息。适用于需要自动化微信操作的场景,如定时发送、批量回复、消息备份等。依赖 peekaboo 进行屏幕截图和 UI 交互。仅支持 macOS。开源地址:https://github.com/chairmanmia...
- 先用 store 构造每个中间件的第一层,得到:
loggerAPI、thunkAPI、errorHandlerAPI(都含 getState/dispatch) - 再按顺序调用:
loggerAPI(thunkAPI(errorHandlerAPI(store.dispatch))) - 最终生成的 dispatch 是一个函数,调用它时触发:
→ logger 开始(外层)
→ thunk 开始
→ errorHandler 开始
→ store.dispatch 执行(最内层)
→ errorHandler 结束(返回后)
→ thunk 结束
→ logger 结束
关键细节:next 不是固定值,而是动态链
很多人误以为 next 就是“下一个中间件函数”,其实 next 是已经柯里化完成的下一层函数,也就是:next = 下一个中间件(store)(更下一个中间件(store)(...))
- 调用
next(action),等于把 action 推进下一层;不调,就中断流程(如 saga 中等待异步完成才调 next) - 可以在调用 next 前/后插入逻辑,实现“进入前”和“退出后”的对称处理(比如 logger 打印前后 state)
- 可以修改 action 再传给 next(如 thunk 把函数 action 转为普通 action),也可以直接 return 早退(如权限中间件拒绝非法 action)
手动模拟洋葱剥开效果的小例子
不用 Redux,也能看清柯里化如何驱动洋葱流:
const A = store => next => action => {
console.log('A before');
const result = next(action);
console.log('A after');
return result;
};
const B = store => next => action => {
console.log('B before');
const result = next(action);
console.log('B after');
return result;
};
const baseDispatch = action => console.log('→ reducer runs:', action);
// 手动串联:A(store)(B(store)(baseDispatch))
const enhanced = A({})(B({})(baseDispatch));
enhanced('test');
// 输出:A before → B before → → reducer runs: test → B after → A after










