当自己自定义一个中间件的时候,基本代码结构:
function applyMiddleWare() {
return ({getState,dispatch})=> (next)=>(action)=>{
}
}
applyMIddleWare源码:
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
在上面的源码中可以看到一个很明显的问题那就是:
const store = createStore(reducer, preloadedState, enhancer)
//这一段代码说明一个问题,那就是在createStore的过程中运用到了applyMiddleware函数
//那么createStore这个动作实际上是在applyMiddleware中完成的。
上面的解释可以在createStore的源码中得到印证:
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
我觉得这种处理方式的原因主要是保证,在store.dispatch函数调用的时候首先经过middleware进行处理。只有在applyMIddleware的函数内创建store才能对dispatch进行包装和处理。
appliMiddleware处理中间件的核心代码就是 :
dispatch = compose(...chain)(store.dispatch)
次行代码作用就是将代码整合在一起、
*from right to left. For example, compose(f, g, h) is identical to doing
* (...args) => f(g(h(...args))).
这是redux compose 源码中对于compose的注释,说明了compose的大概作用。这种函数关系,保障了中间件通过next参数从第一个一直调用到最后一个,就像一个水管一样,对每一个action进行修饰,操作。
而在我们的自定义中间件中,我们可以看到,函数的嵌套层级一般是三级
({dispatch,getState})=>(next)=>(action)=>{}
而下面的代码,就是对应的第一层,将store中的关键api传入中间件,使得每一个中间件,都可以直接调用dispatch和getState
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
而第二层的(next)=>(action) =>{} 对应:
dispatch = compose(...chain)(store.dispatch)
这一行代码,足够简练,却非常难理解。
其中后面括号中的(store.dispatch) 是传给最后一个中间件最为 next参数,
所以,在最后一个中间件调用 next({type:''}) 和 dispatch({type:''}) 本质上是一样的因为 next就是dispatch
而之前的中间件next参数是** 后一位中间件**的(action) => {} 这个层级的函数。
所以之前的中间件中next参数调用的是后一个中间件,和直接dispatch是不一样的
网友评论