美文网首页redux
redux的applyMiddleware的第二部分细节

redux的applyMiddleware的第二部分细节

作者: xiaohesong | 来源:发表于2018-12-01 12:53 被阅读12次

    原文: redux的applyMiddleware细节分析

    上篇文章中有提到中间件里有定义一个dispatch方法用来抛出异常,然后在middlewareAPI里调用的时候是携带参数了:

    const middlewareAPI = {
       getState: store.getState, //获取store里的state
       dispatch: (...args) => dispatch(...args) // 调用`dispatch`的时候会抛错,如果在组合中间件之前调用,下面会说
    }
    

    一开始我以为是在调用的时候就会报错,可是发现这个对象里的dispatch携带参数,如果只是单纯抛错,完全可以不需要传递参数,然后向下看下去才看到其中的奥妙。

    到底奥妙在哪里,这段抛错代码究竟是有什么作用。

    先说这段代码的作用: 防止在对dispatch扩展之前调用dispatch

    我们来写个简单的middleware:

    const exampleMiddle = ({getState, dispatch}) => next => action => {
        console.log('exampleMiddleware action is', action)
        return next(action) 
    }
    

    假设我们当前并不知道那段dispatch函数抛出错误的作用,我们可以根据applyMiddleware代码来推算出来。

    我们知道,在代码里有对dispatch重新赋值操作:

    dispatch = compose(...chain)(store.dispatch)
    

    所以我们可以知道,在这个赋值之前调用的dispatch都是会抛错的(就是那段单纯抛出错误的dispatch函数)。

    所以为了证明这个,我们来试下:

    const exampleMiddle = ({getState, dispatch}) => next => {
      console.log('dispatch action', dispatch({}))
      return action => {
        console.log('exampleMiddleware action is', action)
        return next(action)
      }
    }
    

    然后你就会发现console里有错误抛出,就是那段dispatchthrow

    然后我们在dispatch = compose(...chain)(store.dispatch)之后再次调用dispatch
    也就是在最终触发action的时候再调用,发现是可以调用(需要加判断是否调用过,否则就会死循环。后面解释为啥死循环。)

    会不会感觉不太对,为啥在闭包作用域链外的更改会影响到闭包内的变量?

    先来证明,闭包内的变量不受外部改变:

    let name = 'first arg'
    function run(firstArg){
      console.log('run params is', firstArg)
      return function next(){
        console.log('next params is', firstArg)
      } 
    }
    let next = run(name)
    name = 'changed'
    next() // next params is first arg
    

    对吧,说明外部的更改是不会影响到内部的变量的。因为作用域链已经生成了。

    我们再来看看另外一个情况:

    let age = 99
    let obj = {
      old: age,
      young: () => age
    }
    age = 18
    obj.old // 99
    obj.young() // 18
    

    很明了了吧,因为每次函数调用的都是当前作用域链的变量。如果对于这部分不理解,可以看这篇文章进行深入了解。

    可以发现我们自己写的exampleMiddleware里,第一个参数里有传入dispatch,然后返回的参数里携带了一个next参数(store.dispatch), 为什么还要传递dispatch, 并且dispatch也不可以在前面使用,只能在到action这步的时候才可以。所以为啥还要传递dispatch进来,直接传递了store.dispatch不是更好吗? 这两个不等价,store.dispatch是原生的dispatch,所以可以直接返回,不会出现死循环。参数dispatch是组合中间件之后的dispatch,所以简单的直接调用会死循环,会自己调用自己,所以需要判断下。

    总结: middlewares通过compose组合这些中间件成一个链式的dispatch,这样每次dispatch都会运行处理,可以发现dispatch源码里,最后返回的是action

    相关文章

      网友评论

        本文标题:redux的applyMiddleware的第二部分细节

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