You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
const store = createStore(reducer, applyMiddleware(thunk));
export store
if(typeof enhancer !== undefined){
if(typeof enhancer !== 'function'){
throw new Error('Expected the enhancer to be a function.');
}
return enhancer(createStore)(reducer, preloadedState)
}
applyMiddleware.js
applyMiddleware帮助我们将第三方的中间件,转换成能增强store的enhancer。
下面是一个运用redux-thunk的例子:
可以看到applyMiddleware接收中间件,执行返回的结果就是一个能增强store的enhancer。
还记得在createStore.js里有这么一段代码吗?:
可以看到,在createStore中,如果发现传入了合法的enhancer,就会将逻辑交给enhancer执行,让它返回增强后的store。
结合两段代码,我们可以推测出applyMiddleware函数的大致模样:
下面我们看一下applyMiddleware.js里的具体源码:
可以看到,这个函数做了以下几件事情:
下面重点讲解会让人迷惑的第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)
分成两部分执行compose执行后,我们可以得到这么一个函数, 我们将它命名为composeThunk:
其实注意观察,这里我们调用的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中最为复杂的一个函数了,虽然代码量不多,但是运用闭包的技巧和函数式思想让人折服。
The text was updated successfully, but these errors were encountered: