美文网首页
redux applyMiddleWare源码笔记

redux applyMiddleWare源码笔记

作者: strong9527 | 来源:发表于2017-04-24 10:30 被阅读40次

当自己自定义一个中间件的时候,基本代码结构:


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是不一样的

相关文章

网友评论

      本文标题:redux applyMiddleWare源码笔记

      本文链接:https://www.haomeiwen.com/subject/xnvuzttx.html