redux的中間件相當于改寫store的dispatch方法。
redux-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.`
)
}
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
通過以下兩行源碼
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
可推導出redux給middleware函數(shù)暴露了通用的api,所有的middleware必須寫成
export default ({getState, dispatch} => next => {
...
})
其中next函數(shù)就是store的dispatch的引用,中間件內(nèi)部可以使用。此后dispatch方法會被改寫,中間件內(nèi)部的dispatch也是改寫后的dispatch。
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;
redux-thunk就是通過改寫dispatch方法實現(xiàn)兼容異步更改state的。注意next才是redux本身的dispatch方法的引用,中間件中的dispatch是compose(...chain)(store.dispatch)的返回值,已經(jīng)被改寫了。