什么是中间件?
中间件就是在不影响现有功能的基础上,添加一些额外的功能。采用的思想就是组合的思想。
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('')
}
// 中间件ApplyMiddleware
const 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
}
}
}
}
- 我们希望在创建