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;
这里面有连续三个=> 看起来更晕了。哈哈。可以分布来看下
applymiddleware中这里面我们调用了middleware 并且传入了middlewareAPI 看是不是就是{ dispatch, getState}这个参数。
而这里我们又调用了一次,并且传递了store.dispatch。实际上就是这里的next参数。这个匿名函数参数是next,即传递过来的store.dispatch。返回了一个函数,参数为action,返回的这个函数即一个store.dispatch。然后我们可以通过根据这个action类型来判断该怎么处理。
函数很简单,设计很精妙。读源码确实能学习到很多知识。