hello,大家好,之前我们大概分析了一下createStore中的代码,但应该还是有很多迷迷糊糊的,感觉不知所以。毕竟这个redux中有很多的牵扯,所以当你把整个redux源码都看了一遍,就会大概的了解redux的原理 下面我们来分析一下applyMiddleware export default function applyMiddleware(...middlewares) { // 传入中间件的数组 return (createStore) => (reducer, preloadedState, enhancer) => { 返回一个函数 const store = createStore(reducer, preloadedState, enhancer) // 创建store let dispatch = store.dispatch // 获得store的dispatch let chain = [] // 声明空数组 用来存储action增强函数 const middlewareAPI = { // getState: store.getState, // 通过store获取state dispatch: (action) => dispatch(action) // dispatch方法 } // 传进来的middlewares 进行遍历 返回新数组 chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) // 使用compose进行柯里化 // 在使用了middleWare的情况下,这里就是我们createStore的返回值。 return { ...store, dispatch } }
大体代码是做什么的已经用注释讲解了,但是可能大家还是有一点朦朦的。
例如为什么applyMiddleware这个函数 又返回了一个多重箭头函数, 为什么disaptch这样就能增强action
这个就会牵扯到我们上一篇讲的createStore
const enhancer = compose( applyMiddleware(...middlewares) );
const store = createStore( combineReducers({ ...reducers }), initialState, enhancer );
这里的enhancer 等价于 applyMiddleware(...middlewares)
在createStore中传入enhancer 和 applyMiddleware(...middlewares)效果是一样的。
所以相当于applyMiddleware(...middlewares)这个就是createStore传入的 enhancer,在createStore中enhancer要求是一个函数,
现在我们看看applyMiddleware(...middlewares)的返回结果,这里返回了一个函数。
if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) }
从上面的代码我们可以看到我们首先将createStore传入 applyMiddleware(...middlewares)返回的函数中,然后在将state和reducer传入到enhancer(createStore)返回的函数中。
这样我们就可以知道在我们传入中间件的情况下
const store = createStore(reducer, preloadedState, enhancer) // 创建store
这一行代码才是创建store执行者。
然后我们通过创建的store或者state 和 dispatch 然后创建了一个middlewareAPI 并将其传入middleware中,
这是为了让中间件可以直接和store来进行沟通。
接下来的两行代码可以说是applyMiddleware中最核心的代码了
chain = middlewares.map(middleware => middleware(middlewareAPI))
首先通过map将其遍历 执行中间件。
我们用一下redux-thunk的源码来进行对应的讲解
redux-thunk源码:
function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
这里获得的thunk 是createThunkMiddleware的执行结果 thunk相当于
({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); };
当我们只有middleWare中只有一个thunk的时候
这时候我们applyMiddleware中的 middlerwares = [ thunk ]
chain = middlewares.map(middleware => middleware(middlewareAPI))
就相当于 chain = middlewares.map(thunk = thunk(middlewareAPI));
执行结果: chain = [ thunk() ]
关于thunk多重箭头函数中的next 和 action 是从哪里来的呢?
具体是由于下面这一句代码的执行,所引起的
dispatch = compose(...chain)(store.dispatch)
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))) }
以上是compose的源码
我们看一下里面最核心的就是最后一句代码
return funcs.reduce((a, b) => (...args) => a(b(...args)))
这里使用了reduce操作,我们假设传进去的数组里面有3个中间件A,B,C,然这执行后返回的结果为(..args)=>A(B(C(...args))) 这样一个函数。
然后我们在看看dispatch = compose(...chain)(store.dispatch) 这一行,我们将store.dispatch 传递了进去,所以我们 上面的
(..args)=>A(B(C(...args))) => (store.dispatch) => A(B(C(store.dispatch)));
我们这时候可以看看thunk中间件代码,然后结合上面推出来的表达式,我们能看到如果是最后一个中间件,那么他的next是store.dispatch,如果不是最后一个,那么他的next就是 后一个函数的执行结构。
我们可以推断出来 (store.dispatch) => A(B(C(store.dispatch))) 这一行的返回结果是
以thunk代码为例: 我们执行后会返回这样一个箭头函数。 我们下文将这个箭头函数简称为Action函数
action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); };
所以不管有多少个中间件我 compose(...chain)(store.dispatch) 这里返回的一定是Action函数,
然后把这个赋值给dispatch,这个dispatch就是我们正常使用的dispatch函数。
我们在使用redux的时候会调用dispatch这个方法 eg: disptach(action) ;
在我们调用的时候我们将action传递进去,然后传递到 compose(...chain)(store.dispatch) 返回的函数,执行函数体,然后我们最后返回next(action) 这里的next指向下一个中间件的 Action函数,直到最后面指向store.dispatch;
现在基本解释完了,我们接下来看源码 最后返回了一个对象里面返回了创建的store对象,和增强后的dispatch方法。