什么是中间件?
中间件就是在不影响现有功能的基础上,添加一些额外的功能。采用的思想就是组合的思想。
redux的中间件
redux的中间件的功能是一样的。是为了增强dispatch的功能。
基础使用
const logger1 = (store: MiddlewareAPI) => (next: Dispatch) => (action: any) => {console.log('中间件1')console.log('旧数据', store.getState())console.log('action', action)next(action)console.log('新数据', store.getState())console.log('')}const logger2 = (store: MiddlewareAPI) => (next: Dispatch) => (action: any) => {console.log('中间件2')console.log('旧数据', store.getState())console.log('action', action)next(action)console.log('新数据', store.getState())console.log('')}// 中间件ApplyMiddlewareconst store = createStore(rootReducer, applyMiddleware(logger1, logger2))
执行的顺序
以上面的代码为例:
多个中间件使用的时候,当调用next(action)之前,执行顺序时按照中间件的书写顺序来执行的。当调用next(action)之后的代码,是按照中间件书写相反的顺序来执行的。
打印顺序为:
中间件1旧数据 {user: Array(2)}action {type: Symbol(ADD_USER), payload: {…}}中间件2旧数据 {user: Array(2)}action {type: Symbol(ADD_USER), payload: {…}}新数据 {user: Array(3)} // --》 中间件logger2新数据 {user: Array(3)} // --》中间件logger1
中间件的返回值:
某一个中间件的返回值会作为下一个中间件next(action)调用的返回值。这里的下一个指的是书写顺序的上一个,上面的例子的话:logger2的中间件的返回值就是logger1中next(action)的执行结果。
实现applyMiddleware的核心功能
applyMiddleware是什么
applyMiddleware是一个函数,同时返回值也是一个函数。
类型定义
export function applyMiddleware<Ext, S = any>(...middlewares: Middleware<any, S, any>[]): StoreEnhancer<{ dispatch: Ext }>
applyMiddleware说明
- 参数:就是中间件数组。
- 返回值:一个增强的
createStore方法,参数就是原来的createStore方法。
就是一个函数:export interface Middleware<DispatchExt = {},S = any,D extends Dispatch = Dispatch> {(api: MiddlewareAPI<D, S>): (next: Dispatch<AnyAction>) => (action: any) => any}
参数:一个MiddlewareAPI对象。
返回值:一个函数
参数是Dispatch方法
返回值是一个函数(dispatch方法),参数自然就是action。
export type StoreEnhancer<Ext = {}, StateExt = {}> = (next: StoreEnhancerStoreCreator) => StoreEnhancerStoreCreator<Ext, StateExt>export type StoreEnhancerStoreCreator<Ext = {}, StateExt = {}> = <S = any,A extends Action = AnyAction>(reducer: Reducer<S, A>,preloadedState?: PreloadedState<S>) => Store<S & StateExt, A> & Ext
代码实现
首先
appluMiddleware接受的是一个中间件的数组,返回值是一个增强的createStore。我们可以写出如下的代码。export default function applyMiddleware(...middlewares: Middleware[]) {return (createStore: StoreEnhancerStoreCreator) => {return <S, A extends AnyAction>(reducer: Reducer,preloadState: PreloadedState<S>) => {}}}
由于返回的是一个增强版的
createStore,createStore的基本功能应该实现。export default function applyMiddleware(...middlewares: Middleware[]) {return (createStore: StoreEnhancerStoreCreator) => {return <S, A extends AnyAction>(reducer: Reducer,preloadState: PreloadedState<S>) => {const store = createStore(reducer, preloadState)return {...store}}}}
由于中间件的主要作用是用于增强
dispatch方法的。怎么增强呢?- 我们希望在创建
store之后,store触发dispatch之后,除了进行相应的reducer的操作,还希望有额外的功能。 - 这说明:我们调用的
dispatch是经过包装之后的dispatch方法。 - 然后,传入的中间件函数每一个都是用于创建
dispatch方法的方法。 - 不然的话,使用同一个创建
dispatch方法,store可能是不一样的。我们包装的dispatch方法肯定还是根据store的dispatch方法来的。 - 所以:我们首先将所有创建
dispatch方法的函数创建出来。export default function applyMiddleware(...middlewares: Middleware[]) {return (createStore: StoreEnhancerStoreCreator) => {return <S, A extends AnyAction>(reducer: Reducer,preloadState: PreloadedState<S>) => {// 不能在构建dispatch链式调用的时候调用。也就是说,不能再middlewares函数中调用const dispatch: Dispatch = () => {throw new Error('Dispatching while constructing your middleware is not allowed. ' +'Other middleware would not be applied to this dispatch.')}const store = createStore(reducer, preloadState)const middlewareAPI: MiddlewareAPI = {getState: store.getState,dispatch: (action, ...args) => dispatch(action, ...args)}const chain = middlewares.map(middleware => middleware(middlewareAPI))// 这样传递之后,chain数组里面全是生成dispatch的方法// 然后我们就要确定生成后的dispatch被调用后,怎么传递调用的值。return {...store,dispatch}}}}
- 我们希望在创建
