redux中的middleware

1 使用

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

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

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

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的实现很是简单:spa

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中的每个函数的结构均为:rest

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

对于函数g,执行g(dispatch)至关于返回一个函数:code

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

所以,对于d = compose(f, g)(dispatch),即至关于返回了一个函数:get

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

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

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

相关文章
相关标签/搜索