我在这里梳理下redux中间件的原理,首先说两个概念,store enhancer 与 dispatch enhancer。createStore(reducer, initState, enhancer)第三个参数就是store enhancer 是用来增加store的,除了可以扩展dispatch还可以扩展其他东西,我们平时用的midddleware则是dispatch enhancer。
store enhancer 函数签名为:(createStore) =>( reducer, preloadedState) => store
middeware 函数签名:({getState,dispatch}) => next => action => next(action)或其他
我们平时使用的window.__REDUX_DEVTOOLS_EXTENSION和applyMiddleware都属于store enhancer creater, 执行之后生成 store enhancer
源码解析:
export default function applyMiddleware(...middlewares) {
return (createStore) =>( reducer, preloadedState) => {
const store = createStore(reducer, preloadedState)
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
// 第一步(执行第一层): 传入统一的getState、dispatch
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 第二步(compose组合): 生成 (...args) => mid1(mid2(args))
// 第三步(执行)
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
// 这里我们举个例子有两个中间件:1 >> 3 代表了中间件的三层结构
// middleware的签名:({getState,dispatch}) => next => action => f
function mid1_1 ({ dispatch, getState }) {
return function mid1_2 (next) {
return function mid1_3 (action) {
console.log('当前action1: ', action)
next(action)
console.log('更改之后的store1:', dispatch, getState())
}
}
}
function mid2_1 ({ dispatch, getState }) {
return function mid2_2 (next) {
return function mid2_3 (action) {
console.log('当前action2: ', action)
next(action)
console.log('更改之后的store2:', dispatch, getState())
}
}
}
// 在使用applymiddleware 的过程中,我们只关注三个关键步骤:
// 第一步:const chain = middlewares.map(middleware => middleware(middlewareAPI)),每个中间件得到了同样的getState 和 dispatch(暂时为假的,防止在创建过程中调用dispatch),得到如下结果
chain = [mid1_2, mid2_2]
// 第二步:compose 将上面的中间件数组组合成一个大函数,mid2-2的结果,做为mid1_2的 next参数,下一步会传入真正的dispatch,则最后一个中间件的next 为dispatch,其他中间件的next则为后面中间件的返回结果
function (...args) {
return mide1_2( mid2_2(args) )
}
// 第三步:执行上面得到的函数,传入真正的dispatch得到最终的dispatch函数
function mid1_3 (action) {
console.log('当前action1: ', action)
mid2_3(action)
console.log('更改之后的store1:', getState())
}
// 此时mid1_3 与 mid2_3 的内部
mid1_3 中:
dispatch: 改造之后的dispatch(dispatch = compose(...chain)(store.dispatch),改变了之前的dispatch)
getState: 原生的store.getState
next: 变为mid2_3函数
mid2_3中:
dispatch: 改造之后的dispatch
getState: 原生的store.getState
next: store.dispatch