Store增强器(StoreEnhancer)
在createStore
函数中有一个enhancer
参数,StoreEnhancer
类型。enhancer
本质其实是一个高阶函数,执行此函数,返回增强后的store
。
/**
* @param enhancer store增强器. 你可以选择指定它以增强store的第三方功能,如中间件,时间旅行,持久性等。
* Redux 附带的唯一存储增强器是“applyMiddleware()”.
*
* @returns A Redux store that lets you read the state, dispatch actions
* and subscribe to changes.
*/
export default function createStore(reducer: Reducer<S, A>, preloadedState?: PreloadedState<S> | StoreEnhancer, enhancer?: StoreEnhancer){
// 如果第二个参数preloadedState是函数类型,并且第三个参数enhancer不存在,就把preloadedState作为增强器。
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState as StoreEnhancer<Ext, StateExt>
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// 执行增强器函数,返回Store,不在执行后续的初始化Store,由增强器内部执行初始化Store的操作。
return enhancer(createStore)(
reducer,
preloadedState as PreloadedState<S>
) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
}
}
StoreEnhancer
类型,声明方式如下:
const enhancer = createStore => (reducer, preloadedState): Store => { };
applyMiddleware
applyMiddleware
函数的返回值类型则是StoreEnhancer
类型,需要返回上述的高阶函数。
- 给每个中间件传递参数:
getState
和dispatch
; - 中间件相互组合,形如
a(b(c(store.dispatch))
,返回新的dispatch;
export default function applyMiddleware(...middlewares: Middleware[]): StoreEnhancer<any> {
return (createStore: StoreEnhancerStoreCreator) => (
reducer: Reducer<S, A>,
preloadedState?: PreloadedState<S>
) => {
const store = createStore(reducer, preloadedState)
let dispatch: Dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
// 这里的middlewareAPI.dispatch是传递给中间件的一个参数
// 当真正调用middlewareAPI.dispatch的时候,会执行内部的dispatch方法,
// 而此时这个dispatch已经被下面的代码重新赋值,进行了功能增强
const middlewareAPI: MiddlewareAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
// 为每个中间件设置getState和dispatch参数,触发的是中间件外层函数的调用。
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 组合中间件,触发的是中间件第二层函数的调用,入参是下一个中间件第二层函数调用的返回函数,ji。
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
compose可以换一种写法
let dispatch = store.dispatch;
chain.reverse().map(dispatchFunc=>{
dispatch = dispatchFunc(dispatch);
});
return {
...store,
dispatch
}
目的是实现形如a( b( c(store.dispatch) ) )的洋葱调用模型
中间件
中间件声明如下:
const middleware = ({getState, dispatch}) => next => action => {
// TODO
}
如下两个中间件源码都满足上述声明,
redux-thunk中间件
改造store.dispatch
,使得dispatch
可以接受Function
类型的action
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-promise源码
改造store.dispatch
,使得dispatch
可以接受Promise
类型的action
,或者接受Action 对象的payload属性是一个 Promise 对象。
import isPromise from 'is-promise';
import { isFSA } from 'flux-standard-action';
export default function promiseMiddleware({ dispatch }) {
return next => action => {
if (!isFSA(action)) {
return isPromise(action) ? action.then(dispatch) : next(action);
}
return isPromise(action.payload)
? action.payload
.then(result => dispatch({ ...action, payload: result }))
.catch(error => {
dispatch({ ...action, payload: error, error: true });
return Promise.reject(error);
})
: next(action);
};
}