美文网首页
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