以下是一个手写的 Redux 中间件示例及其实现原理说明。我们以创建一个日志中间件为例,演示如何编写中间件:
完整代码实现
// 手写日志中间件
const loggerMiddleware = (store) => (next) => (action) => {
// 1. 记录触发前的状态
console.log('dispatching action:', action);
console.log('current state:', store.getState());
// 2. 将 action 传递给下一个中间件或 reducer
const result = next(action);
// 3. 记录处理后的新状态
console.log('next state:', store.getState());
// 4. 返回处理结果 (通常是 action 本身)
return result;
};
// 使用示例
import { createStore, applyMiddleware } from 'redux';
const store = createStore(
rootReducer,
applyMiddleware(loggerMiddleware)
);
中间件结构解析
Redux 中间件采用三层嵌套函数结构:
const middleware = (store) => (next) => (action) => {
// 中间件逻辑
}
-
外层函数 (
store)
接收包含dispatch和getState方法的 store 对象 -
中层函数 (
next)
接收链中下一个中间件的dispatch方法
(如果是最后一个中间件,则next指向原始store.dispatch) -
内层函数 (
action)
处理 action 的逻辑
高级中间件示例:异步处理
实现类似 redux-thunk 的异步处理能力:
const thunkMiddleware = ({ dispatch, getState }) => (next) => (action) => {
// 如果 action 是函数,执行它并传入 dispatch/getState
if (typeof action === 'function') {
return action(dispatch, getState);
}
// 否则直接传递 action
return next(action);
};
// 使用方式:
dispatch((dispatch) => {
setTimeout(() => {
dispatch({ type: 'ASYNC_ACTION' })
}, 1000)
})
核心实现要点
-
中间件链式调用
每个中间件通过next()将 action 传递给下一个中间件 -
两种 dispatch 区别
next(action):传递给后续中间件store.dispatch(action):重新走完整中间件链
-
状态获取时机
store.getState()在next()前获取当前状态store.getState()在next()后获取新状态
中间件执行流程图
原始 dispatch
↓
中间件1 (处理 action)
↓ next()
中间件2 (处理 action)
↓ next()
...
↓
原始 reducer 处理
通过这种机制,中间件可以:
- 修改/拦截 action
- 添加异步逻辑
- 记录状态变化
- 实现撤销重做等高级功能