1 使用

const store = createStore(
  rootReducer,
  applyMiddleware(
    thunkMiddleware, // lets us dispatch() functions
    loggerMiddleware // neat middleware that logs actions
  )
)

其中applyMiddleware(...)是一个enhancer。enhancer在redux中的作用会代理createStore方法返回具有增强效果的store.

applyMiddleware接收一系列middlewares。一个典型的middleware是长这样的:

export default function thunkMiddleware({ dispatch, getState }) {
  return next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState);
    }

    return next(action);
  };
}

applyMiddleware在接收到middleware后,会进行如下处理:

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, initialState, enhancer) => {
    var store = createStore(reducer, initialState, enhancer)
    var dispatch = store.dispatch
    var chain = []

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    // 将middleware初始化,些时chain里是Array<next=>action=>doSomething>
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

重点是后面的compose语句。compose的实现非常简单:

export default function compose(...funcs) {
  return (...args) => {
    if (funcs.length === 0) {
      return args[0]
    }

    const last = funcs[funcs.length - 1]
    const rest = funcs.slice(0, -1)

    return rest.reduceRight((composed, f) => f(composed), last(...args))
  }
}

接收一堆参数fns,返回另一个函数。在这个函数里,将参数中的函数逐个从右到左执行,上一个执行的结果将做为下一个执行的参数。

compose(f, g, h)(100)相当于f(g(h(100))). 而对于上面的dispatch = compose(...chain)(store.dispatch),由于chain中的每一个函数的结构均为:

function g(next) {
  return  function (action) {
     // do something
  }
}

对于函数g,执行g(dispatch)相当于返回一个函数:

function (action) {
  // 这个函数中,next的值为dispatch
}

因此,对于d = compose(f, g)(dispatch),即相当于返回了一个函数:

  • 这个函数长的是这样的: function f1(action) {/* 函数体中的next为g1*/}

  • g1的定义是function g1(action) {/* 函数体中的next为dispatch*/}

这样通过调用d,层层next下去,最终就调到了dispatch了。
注:由于上面的chain = middlewares.map(middleware =>middleware(middlewareAPI)),每一个middleware都能直接访问到store.dispatch,每个middleware都可以在任意时刻进行dispatch,之所以最后一个next被弄成了dispatch,可能只是为了让默认行为是dispatch.


ssnau
1.5k 声望98 粉丝

负能量职业打码师


« 上一篇
npm下常用mirror

引用和评论

0 条评论