redux-applyMiddleware

redux 中的middleware思想还是很巧妙地,先来看下怎么使用

export default function createStore(initialState = {}) {
  const middleware = [thunkMiddleware, promiseMiddleware, messageMiddleware];
  let finalCreateStore;
  finalCreateStore = applyMiddleware(...middleware)(_createStore);
  const store = finalCreateStore(reducer, initialState);
  return store;
}

就是将middleware 使用applymiddleware函数包装一下,再将store传递过去即可,使用起来很简单,那么关键就是这个applymiddleware函数了,这个函数式redux提供的,先来看下源码:

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)
    }

    // 依次调用传进来的middleware 并且调用middleware  传入 middlewareAPI
    chain = middlewares.map(middleware => middleware(middlewareAPI))

    //依次调用传入了middlewareAPI 的 middleware集合 再传入一个dispatch 再返回
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...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)))
}

可能上面有注释这两句看起来有点晕, 其实多看几次就明白了。这里用了componse函数,在下面也有给出。
applymiddleware函数我们看完了, 那么middleware我们怎么来写呢?这里给出一个例子,就是著名的redux-thunk的代码,这么著名的第三方库实际上只有那么几行。

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

这里面有连续三个=> 看起来更晕了。哈哈。可以分布来看下


image.png

applymiddleware中这里面我们调用了middleware 并且传入了middlewareAPI 看是不是就是{ dispatch, getState}这个参数。

image.png

而这里我们又调用了一次,并且传递了store.dispatch。实际上就是这里的next参数。这个匿名函数参数是next,即传递过来的store.dispatch。返回了一个函数,参数为action,返回的这个函数即一个store.dispatch。然后我们可以通过根据这个action类型来判断该怎么处理。

函数很简单,设计很精妙。读源码确实能学习到很多知识。

推荐阅读更多精彩内容