前言
- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是学习源码整体架构系列的第8期,链接:学习 redux 源码整体架构,深入理解 redux 及其中间件原理 - 掘金 (juejin.cn)。
源码
Redux.applyMiddleWare()
他其实做的就是,用于增减
store
首先看一下用法,中间件可以作为createStore()第二个或者第三个参数传进去
var store = Redux.createStore(counter, Redux.applyMiddleware(logger1))
//或者
var store = Redux.createStore(counter, preState,Redux.applyMiddleware(logger1))
那么上面那篇文章只是减少了createStore里面的几个函数,那么我们现在来看一下需要的形参
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接受三个参数
reducer:就是那个接受action和preState的函数,返回新的statepreloadedState:stateenhancer:我们传入中间件的地方
从最后一行代码看出,当我们传入中间件的时候,我们就会去调用这个enhancer(createStore)(reducer, preloadedState)函数
enhancer--中间件函数
当我们打断点的时候,发现其实,他先执行的是applyMiddleware()这个函数,在这个函数里面去调用createStore函数,至于为什么,我们可以理解为,执行栈问题
- 首先
Redux.createStore()入栈 - 在这个里面因为调用了
applyMiddleware(),所以applyMiddleware()入栈 applyMiddleWare()执行完成,出栈,所有,执行createStore
如果你感到困惑,我们可以在createStore.js里面输出调试一下
enhancer:里面是啥
console.log("enhancer",enhancer)
其实这里的createStore()不是那个createStore():Redux里的createStore函数,只是同名而已
那么我们现在来好好看一下这个代码enhancer(createStore)(reducer, preloadedState)
- 首先肯定是调用了
enhancer()这个函数,也就是那个createStore()函数(这边我改名为createStore1)
export default function applyMiddleware(...middlewares) {
console.log("middleWares",...middlewares);
return createStore1 => (...args) => {
console.log("args11",args);
const store = createStore1(...args)
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
我们来分析一下,执行栈里面
-
首先,
enhancer(createStore),enhancer函数入栈- 从上面我们可以知道
enhancer其实就是createStore1()这个函数 - 观察
createStore1(),其实是一个箭头函数,返回值还是一个函数
- 从上面我们可以知道
-
因为后面继续调用了函数
enhancer(createStore)(reducer, preloadedState)-
所以调用了
createStore1()返回的函数,并且传入参数reducer和preloadedState -
因为
enhancer()传入了参数createStore,然后函数调用,其实createStore就是createStore1 -
const store = createStore1(...args)的时候又去执行了Redux.createStore(),并且将参数带过去 -
因为参数使
redcer和perloadedState -
所以
createStore的参数也就变为了reducer, preloadedState, enhancerreducer:functionpreloadedState:undefinedenhancer:undefined
-
这样我们这个
store就拥有了getstate()和dispatch()方法,那么我们createStore()方法return {dispatch,getState...},那么,我们createStore1这个函数出栈,继续往下执行- 那么继续往下执行那个箭头函数
(...args)=>{}
-
const chain = middlewares.map(middleware => middleware(middlewareAPI)),这里面是很多个中间件函数- 他们都有一个参数
middleWareAPI,再去执行logger1这个中间件函数
- 他们都有一个参数
-
-
其实增强的
dispatch()函数,则是用dispatch = compose(...chain)(store.dispatch)执行的
redux.compose()
用于组合传入的函数
compose这个方法,主要用来组合传入的一系列函数,在中间件时会用到。可以看到,执行的最终结果是把各个函数串联起来。
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
//return funcs.reduce((a, b) => (...args) => a(b(...args)))
return funcs.reduce(function(a, b){
return function(...args){
return a(b(...args));
};
}
);
}
箭头函数并没有那么好理解,我们可以将箭头函数变为普通函数
arr.reduce()
这其实就是一个累加器,他将数组的每个值从左往右的开始缩减,最终计算为一个值
reducer()里面会放入一个函数,就是希望当前数组的变为什么样子的数组
我们可以件源码改变一下
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
const composing = (a, b) => {
console.log("a", a)
console.log("b", b)
return (...args) => {
console.log("composing_args",args)
return a(b(...args))
}
}
return funcs.reduce(composing)
}
假设我们现在compose(f,g,h)
- 最开始数组是
[f,g,h] - 从左往右执行,第一次过后,数组变为
[f(g()),h] - 第二次变为了
[f(g(h()))]
源码的意思:
也就是每次都在外层添加一个函数,就是件这个函数的返回值作为参数传给另一个参数
那么我们现在返回的结果其实就是:一个正常的Store和一个被变更过的dispatch方法
总结
上次夸下海口说:11.5号就看完中间件这部分,奈何行动力太差了,兜兜转转到今天才把中间件看完。
redux的middleware适用于增强dispatch出现的
感觉对redux没有那么迷惑了
但是后续还是需要再好好了解一下,因为,感觉才只懂了一点皮毛🤦♀️