欢迎关注redux源码分析系列文章:
redux源码分析之一:createStore.js
redux源码分析之二:combineReducers.js
redux源码分析之三:bindActionCreators.js
redux源码分析之四:compose.js
redux源码分析之五:applyMiddleware
redux中间件其实非常简单,中间件的目的只有一个:在dispatch前后,执行一些代码,达到增强dispatch的效果,有点类似装饰器的原理。
applyMiddleware需要结合createStore函数来看,appleyMiddleware就是createStore的第三个参数enhancer,比如,对redux-logger中间件,其使用方式如下:
import { applyMiddleware, createStore } from 'redux';
import { createLogger } from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
)
applyMiddleware文件的源码如下:
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
一、applyMiddleware函数的参数
- 接受多个参数,每一个参数,都是一个中间件
二、函数的返回值
函数的返回值本身,也是另外一个函数,而这个函数,接受的参数是createStore,结合createStore的前几行源码来看:
export default function createStore(reducer, preloadedState, enhancer) {
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
//其余代码这里忽略
}
可以看到,createStore的第三个参数ehancer如果是一个函数的话,就会优先执行ehancer,然后再再enhancer内部调用createStore函数,所以,createStore其实只会执行一些,也只会生成一个store。
三、关键代码解释
我添加了代码注释如下:(关于compose函数的解释,请参考文章:redux源码分析之四:compose.js):
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
//这里会原封不动的执行createStore,并根据入参生成一个store
const store = createStore(reducer, preloadedState, enhancer)
//把dispatch从store中取出来
let dispatch = store.dispatch
let chain = []
//这里约定了所有的redux中间件只能使用的api就是2个,getState和dispatch
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
对每一个中间件,执行中间件函数,并将中间件api对象传入函数,用chain变量接收中间件执行结果的其返回值
chain = middlewares.map(middleware => middleware(middlewareAPI))
//这里用到了compose函数,分别按顺序从后往前执行每一个中间件,并且前一个中间件的返回值作为后一个中间件的入参,所有中间件的第一个入参是原始的store.dispatch
dispatch = compose(...chain)(store.dispatch)
//最后返回store对象,只是,使用了经过中间件加工过的dispatch对象,替换掉原始的dispatch对象
return {
...store,
dispatch
}
}
}
四、总结
redux中间件只有一个目的:在dispatch前后,执行一些代码,达到增强dispatch的效果,有点类似装饰器的原理。,理解好了这一点就ok了。
下一篇文章会给大家带来一个最简单的redux中间件,敬请期待。