redux源码解析-中间件部分

redux添加中间件需要使用到一个redux原生提供的一个方法 applyMiddleware, 我们就从这个方法说起

整个中间件部分代码不多, 但是函数的嵌套层级较多, 很容易乱

applyMiddleware

先看源码:

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args)
    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: (...args) => dispatch(...args)
    }
    
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

这个函数我们在使用的时候大致是这样的

const store = createStore(reducer, preloadedState, applyMiddleware( thunk, logger ))

所以我们传入createStore的实际是他的返回值 (createStore)=> (...args)=> store—— 一个接收 createStore 函数, 返回另一个接收任意数量参数返回store对象的函数, 我们叫他enhancer

这点你可能会迷, createStore 为什么会出现在这, createStore 自己又干了什么?

至于createStore内部干了什么我们先不多说, 我们先记住:

一旦createStore内部检测到我们传入了enhancer, 就会调用并返回enhancer的执行结果

 if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }

    return enhancer(createStore)(reducer, preloadedState) // 把控制权交给了applyMiddleware
  }

简单来讲enhancer内部就是创建了store, 但是并没有立即把store返回给你用, 而是依照顺序调用你传入的中间件去修改dispatch, 再把修改后的dispatch放进store中返回给你
这里值得注意的就是这个中间件调用顺序

    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

第一行: 正序调用你传入的所有中间件函数, 并保存执行结果数组

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }
  if (funcs.length === 1) {
    return funcs[0]
  }
  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

第二行: 调用这个compose函数对执行结果数组转换格式

funcs.reduce((a, b) => (...args) => a(b(...args)))

第一次看见这种写法应该会迷, 实际就是这样

const funcs = [fun1, fun2, fun3, fun4]
funcs.reduce((a, b) => (...args) => a(b(...args)))
// (...args)=> fun1(fun2(fun3(fun4(...args))))

下一节我们找个中间件的源码套上去试试, 再理解一下中间件的写法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值