redux中间件机制——源码解析
2018-08-14 本文已影响271人
_贺瑞丰
1.中间件是在createStore函数中被作为参数传递的。
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
2.createStore源码拆解
export default function createStore(reducer, preloadedState, enhancer) {
//- 参数位置的调整,使enhancer(也就是中间件)可以出现在第三个或者第二个参数位置上。
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
//这里enhance就是applyMiddleware(...middleware)的执行结果
return enhancer(createStore)(reducer, preloadedState)
}
重点是 return enhancer(createStore)(reducer, preloadedState)
store的创建是交给了enhancer的,并且将这里定义的createStore,reducer, preloadedState等传入了enhancer中。
3.applyMiuddleware返回的是什么?
源码如下:
import compose from './compose'
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)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
执行applyMiuddleware返回的是一个函数:
(createStore)=>(reducer,preloadedstate,enhancer)=>{
//获取store state,和重写dispatch方法,返回全新的store和dispatch
return {
...store,
dispatch
}}
4.createStore中间件模式返回时调用的applymiddleware
return enhancer(createStore)(reducer, preloadedState) ===
returrn applymiddleware(createStore)(reducer, preloadedState)
5. 中间件拿到了createStore之后,负责创建store和重写dispatch
从源码中我们可以看到dispatch是被middlewares处理过,然后用compose拼接起来。 后面我们会举一个具体的middleware的例子
let dispatch = store.dispatch
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
6. compose源码
可以看出如果参数只有1个的我时候,compose没啥用
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)))
}
7. 单中间件:redux-thunk
thunk接受dispatch和getState,这里是从
//在之前重写的dispatch的地方,将store原来的dispatch和getState传入了thunk中
middlewares.map(middleware => middleware(middlewareAPI))
thunk拿到了原来的dispatch和getState并重写。
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;
8.经过redux-thunk修改过的store
可以看出 dispatch现在可以接受函数了
const store = createStore(
reducer,
applyMiddleware(thunk)
)
console.log(store.dispatch);
![](https://img.haomeiwen.com/i7078482/fb2ea163c9edca56.png)