什么是中间件?

中间件就是在不影响现有功能的基础上,添加一些额外的功能。采用的思想就是组合的思想。

redux的中间件

redux的中间件的功能是一样的。是为了增强dispatch的功能。

基础使用

  1. const logger1 = (store: MiddlewareAPI) => (next: Dispatch) => (action: any) => {
  2. console.log('中间件1')
  3. console.log('旧数据', store.getState())
  4. console.log('action', action)
  5. next(action)
  6. console.log('新数据', store.getState())
  7. console.log('')
  8. }
  9. const logger2 = (store: MiddlewareAPI) => (next: Dispatch) => (action: any) => {
  10. console.log('中间件2')
  11. console.log('旧数据', store.getState())
  12. console.log('action', action)
  13. next(action)
  14. console.log('新数据', store.getState())
  15. console.log('')
  16. }
  17. // 中间件ApplyMiddleware
  18. const store = createStore(rootReducer, applyMiddleware(logger1, logger2))

执行的顺序

以上面的代码为例:
多个中间件使用的时候,当调用next(action)之前,执行顺序时按照中间件的书写顺序来执行的。当调用next(action)之后的代码,是按照中间件书写相反的顺序来执行的。
打印顺序为:

  1. 中间件1
  2. 旧数据 {user: Array(2)}
  3. action {type: Symbol(ADD_USER), payload: {…}}
  4. 中间件2
  5. 旧数据 {user: Array(2)}
  6. action {type: Symbol(ADD_USER), payload: {…}}
  7. 新数据 {user: Array(3)} // --》 中间件logger2
  8. 新数据 {user: Array(3)} // --》中间件logger1

中间件的返回值:

某一个中间件的返回值会作为下一个中间件next(action)调用的返回值。这里的下一个指的是书写顺序的上一个,上面的例子的话:logger2的中间件的返回值就是logger1next(action)的执行结果。

实现applyMiddleware的核心功能

applyMiddleware是什么

applyMiddleware是一个函数,同时返回值也是一个函数。

类型定义

  1. export function applyMiddleware<Ext, S = any>(
  2. ...middlewares: Middleware<any, S, any>[]
  3. ): StoreEnhancer<{ dispatch: Ext }>

applyMiddleware说明

  • 参数:就是中间件数组。
  • 返回值:一个增强的createStore方法,参数就是原来的createStore方法。
    1. export interface Middleware<
    2. DispatchExt = {},
    3. S = any,
    4. D extends Dispatch = Dispatch
    5. > {
    6. (api: MiddlewareAPI<D, S>): (
    7. next: Dispatch<AnyAction>
    8. ) => (action: any) => any
    9. }
    就是一个函数:
    参数:一个MiddlewareAPI对象。
    返回值:一个函数
    参数是Dispatch方法
    返回值是一个函数(dispatch方法),参数自然就是action
  1. export type StoreEnhancer<Ext = {}, StateExt = {}> = (
  2. next: StoreEnhancerStoreCreator
  3. ) => StoreEnhancerStoreCreator<Ext, StateExt>
  4. export type StoreEnhancerStoreCreator<Ext = {}, StateExt = {}> = <
  5. S = any,
  6. A extends Action = AnyAction
  7. >(
  8. reducer: Reducer<S, A>,
  9. preloadedState?: PreloadedState<S>
  10. ) => Store<S & StateExt, A> & Ext

代码实现

  • 首先appluMiddleware接受的是一个中间件的数组,返回值是一个增强的createStore。我们可以写出如下的代码。

    1. export default function applyMiddleware(...middlewares: Middleware[]) {
    2. return (createStore: StoreEnhancerStoreCreator) => {
    3. return <S, A extends AnyAction>(
    4. reducer: Reducer,
    5. preloadState: PreloadedState<S>
    6. ) => {}
    7. }
    8. }
  • 由于返回的是一个增强版的createStorecreateStore的基本功能应该实现。

    1. export default function applyMiddleware(...middlewares: Middleware[]) {
    2. return (createStore: StoreEnhancerStoreCreator) => {
    3. return <S, A extends AnyAction>(
    4. reducer: Reducer,
    5. preloadState: PreloadedState<S>
    6. ) => {
    7. const store = createStore(reducer, preloadState)
    8. return {
    9. ...store
    10. }
    11. }
    12. }
    13. }
  • 由于中间件的主要作用是用于增强dispatch方法的。怎么增强呢?

    • 我们希望在创建store之后,store触发dispatch之后,除了进行相应的reducer的操作,还希望有额外的功能。
    • 这说明:我们调用的dispatch是经过包装之后的dispatch方法。
    • 然后,传入的中间件函数每一个都是用于创建dispatch方法的方法。
    • 不然的话,使用同一个创建dispatch方法,store可能是不一样的。我们包装的dispatch方法肯定还是根据storedispatch方法来的。
    • 所以:我们首先将所有创建dispatch方法的函数创建出来。
      1. export default function applyMiddleware(...middlewares: Middleware[]) {
      2. return (createStore: StoreEnhancerStoreCreator) => {
      3. return <S, A extends AnyAction>(
      4. reducer: Reducer,
      5. preloadState: PreloadedState<S>
      6. ) => {
      7. // 不能在构建dispatch链式调用的时候调用。也就是说,不能再middlewares函数中调用
      8. const dispatch: Dispatch = () => {
      9. throw new Error(
      10. 'Dispatching while constructing your middleware is not allowed. ' +
      11. 'Other middleware would not be applied to this dispatch.'
      12. )
      13. }
      14. const store = createStore(reducer, preloadState)
      15. const middlewareAPI: MiddlewareAPI = {
      16. getState: store.getState,
      17. dispatch: (action, ...args) => dispatch(action, ...args)
      18. }
      19. const chain = middlewares.map(middleware => middleware(middlewareAPI))
      20. // 这样传递之后,chain数组里面全是生成dispatch的方法
      21. // 然后我们就要确定生成后的dispatch被调用后,怎么传递调用的值。
      22. return {
      23. ...store,
      24. dispatch
      25. }
      26. }
      27. }
      28. }