Redux源码分析(4) — applyMiddleware 

2023-07-27·5min
type
Post
summary
status
Published
category
tags
slug
date
Jul 27, 2023
password
icon

applyMiddleware.js

applyMiddleware帮助我们将第三方的中间件,转换成能增强store的enhancer。
下面是一个运用redux-thunk的例子:
可以看到applyMiddleware接收中间件,执行返回的结果就是一个能增强store的enhancer。
还记得在createStore.js里有这么一段代码吗?:
可以看到,在createStore中,如果发现传入了合法的enhancer,就会将逻辑交给enhancer执行,让它返回增强后的store。
结合两段代码,我们可以推测出applyMiddleware函数的大致模样:
下面我们看一下applyMiddleware.js里的具体源码:
可以看到,这个函数做了以下几件事情:
  1. 调用传入的createStore,构建一个基础的store
  1. 定一个dispatch方法,这个方法被调用就会报错,注意这个方法在下面会被改写!
  1. 定义一个middlewareAPI对象,里面包含getState方法和会报错的dispatch方法
  1. 使用map方法,将中间件都执行一次,参数是上一步的middlewareAPI对象,得到chain数组
  1. 使用compose方法,将chian数组中的所有函数进行组合,得到一个函数,并赋值给dispatch(改写dispatch)
  1. 返回增强后的store
下面重点讲解会让人迷惑的第4和第5步。

第4步:使用map方法,将中间件都执行一次,参数是上一步的middlewareAPI对象,得到chain数组

为了方便理解,我们这里引入redux-thunk,从头开始分析,下面是redux-thunk的源码:
可以看到导出的thunk是createThunkMiddleware()执行的结果,所以我们得到的thunk是:
当applyMiddleware(thunk)时,applyMiddleware内部得到的middlewares就是:
当到第4步,会使用map方法,将中间件都执行,并传入middlewareAPI, 也就是
这里会执行thunk, 并传入dispatch和getState,执行后,会得到这么一个函数:
所以我们可以知道chain的值:

第5步:使用compose方法,将chian数组中的所有函数进行组合,得到一个函数,并赋值给dispatch(改写dispatch)

redux源码分析(3) — compose里,我们已经讲解了compose的作用。
我们将dispatch = compose(...chain)(store.dispatch)分成两部分执行
1.第一步
compose执行后,我们可以得到这么一个函数, 我们将它命名为composeThunk:
2.第二步
其实注意观察,这里我们调用的composeThunk,本质上也是chianThunk, 所以实际上:
所以我们得到的新dispatch就是:
在applyMiddleware的最后:
会返回一个被强化了dispatch的store,所以所谓的enhancer,其实就是用来强化store的dispatch的。
最后,还有需要补充的是,我们这里只举例了使用一个中间件的情况,其实大多数项目中,我们都会有多个中间件。

多个中间件的情况

假如我们有以下两个中间件:
我们会在第4步后,得到这么两个函数:
当这个chain被第5步compose(...chain)(store.dispatch)调用时,实际情况如下
最后增强后的dispatch就是上方代码的执行结果,每个中间件最后返回的(action) => ...都会成为下一个中间件的next参数。
所以,当一个中间件做完事情后,就可以调用next,将action传递给下一个中间件。
最后贴一下redux-thunk的带注释代码,帮助理解中间件:

结语

applyMiddleware是redux中最为复杂的一个函数了,虽然代码量不多,但是运用闭包的技巧和函数式思想让人折服。
> cd ..