中间件执行顺序
应用了如下的中间件: [A, B, C],
整个执行 action 的过程为 A -> B -> C -> dispatch -> C -> B -> A
==经过applyMiddleware
方法后的dispatch
方法是类似下面,某处调用store.dispatch则传入action, 然后按洋葱模型来执行==
(action) => {
//...
next(action)
//...
}
==最右侧的 next(action)
返回的是应用传入的action
==, 该行为是由redux createStore源码中dispatch方法返回值决定的,不过一般都会 return next(action)
,
前面的中间件的next(action)
的值都是后一个中间件的返回值
小例子
const middleware1 = ({getState, dispatch}) => next => action => {
console.log(`middleware1 before next action `)
console.log(next)
next(action)
console.log(`middleware1 after next action `)
}
const middleware2 = ({getState, dispatch}) => next => action => {
console.log(`middleware2 before next action `)
console.log(next)
next(action)
console.log(`middleware2 after next action `)
}
const middleware3 = ({getState, dispatch}) => next => action => {
console.log(`middleware3 before next action `)
console.log(next)
next(action)
console.log(`middleware3 after next action `)
}
const sagaMiddleware = createSagaMiddleware()
const store = createStore(reducer, applyMiddleware(middleware1, middleware2, middleware3))
被中间件包装过的dispatch方法
是类似于func1(func2(store.dispatch))
这种形式的函数
==next方法其实是此中间件右边中间件的这个方法,你要给它传action。==
(action) => {
//func2中的next是store.dispatch
next(action);
}
==实际的调用顺序是和传入中间件顺序相反的==
let store = applyMiddleware(Middleware1,Middleware2,Middleware3)(createStore)(rootReducer);
实际的执行是次序是store.dispatch->Middleware3->Middleware2->Middleware1。
middlewareAPI中的dispatch被普通函数包装了一下
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
并没有直接使用dispatch:dispatch,而是使用了dispatch:(action) => dispatch(action),其目的是==如果使用了dispatch:dispatch,那么在所有的Middleware中实际都引用的同一个dispatch(闭包),如果存在一个中间件修改了dispatch,就会导致后面一下一系列的问题==,但是如果使用dispatch: (action) => dispatch(action)
就可以避免这个问题。
compose源码
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0, -1)
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}
applyMiddleware 源码
这里chain是函数数组。然后执行compose(...chain)(store.dispatch)。
chain数组的最后一个函数接收store.dispatch函数做为参数,还是返回一个函数,接收action作为参数。这个返回的函数是chain中倒数第二个函数的参数,也就是参数next
[
next => action => {
return next(action)
}
]
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
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;
参考
https://github.com/MrErHu/blo...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。