一句话总结
Middleware就是增强了dispatch
开始调用createStore发生了什么
//调用
const store = createStore(rootReducer, applyMiddleware(...middlewares));
//createStore
export default function createStore(reducer, preloadedState, enhancer)
//如果第二个参数是function,并且没传第三个参数,则将第二个参数赋值给第三个参数,然后将第二个参数设为undefined
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 返回的结果可以解析为
applyMiddleware(...middlewares)(createStore)(reducer, initialState)
applyMiddleware源码里发生了什么
//调用applyMiddleware,可以传入多个中间件
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, initialState, enhancer) => {
var store = createStore(reducer, initialState, enhancer)
var dispatch = store.dispatch
var chain = []
//将state和dispatch所指向的函数绑定到middlewareAPI
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
//迭代中间件数组,并执行一遍,将middlewareAPI作为最外层的store,并返回一个相当于next函数的数组
chain = middlewares.map(middleware => middleware(middlewareAPI))
//将数组整理成嵌套的函数体,并将store.dispatch传入最内侧的函数的next,并返回经过处理的dispatch
//dispatch是一个函数,是一个嵌套了多层的函数,其最里面调用的是store.dispatch
dispatch = compose(...chain)(store.dispatch)
//返回一个新的store
return {
...store,
dispatch
}
}
}
大致看下,其实就是通过一些操作,然后返回一个经过处理的store,dispatch
具体做了些什么
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
- 定义了一个对象(middlewareAPI) ,并将 store.state和store.dispatch绑定到这个对象中(都是引用)
- 然后循环这些中间件,并将middlewareAPI作为参数执行middleware,因为都是高级函数,所以返回的是next数组,并保存到chain中
- 最重要的是下一步的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)))
}
这里有必要解释下funcs.reduce((a, b) => (...args) => a(b(...args))) 这一坨做了些什么?
reduce 是专门为累加操作设计的,啥意思呢
先把funcs.reduce((a, b) => (...args) => a(b(...args))) 翻译一下
- 假如说 funcs[a,b,c,d,e,f]
- 那么执行之后的结果就是a(b(c(d(e(f(...args)))
- 因为是compose(...chain)(store.dispatch)调用,所以...args就是store.dispatch,原生的dispatch,就是说最内层,调用的是原生的dispatch
- 这个有个洋葱模型,网上复制一个
所以最后返回的dispatch是经过处理的dispatch:a(b(c(d(e(f(store.dispatch)))
解释下chain是什么?
//以redux-saga为例
//看参数,就知道为什么定义middlewareAPI对象了
function sagaMiddleware({ getState, dispatch }) {
...
return next => action => {
if (sagaMonitor && sagaMonitor.actionDispatched) {
sagaMonitor.actionDispatched(action)
}
const result = next(action) // hit reducers
channel.put(action)
return result
}
}
- 从源码上可以分析出当执行chain = middlewares.map(middleware => middleware(middlewareAPI))时 直接返回了next()函数
- 当有一堆middleware时,执行middleware都返回一个next()函数
- 所以chain就是一个next()数组
- 而这个next()其实就是下一个middleware
- 一直next到最里面的执行store.dispatch
流程
- 调用applyMiddleware传入n个 middleware
- 用 middlewareAPI 保存了当前的store.state,store.dispatch(每个middleware共享)
- 迭代middlewares,执行每个middleware并携带middlewareAPI,返回一个next()
- 将chain整理成嵌套的函数,最里层调用store.dispatch
- 返回一个经过处理的dispatch
用一个最恶心的方式总结
//模拟三个middleware
function A(next){
return function A1(action){
next(action)
}
}
function B(next){
return function B1(action){
next(action)
}
}
function C(next){
return function C1(action){
next(action)
}
}
假设 dispatch = A(B(C(store.dispatch))),开始执行
function A1(action){
function B1(action){
return function C1(action){
store.dispatch(action)
}
}
}(action)
一个action的执行顺序:A(action) -> B(action) -> C(action) -> store.dispatch(action),先从内到外生成新的func,然后由外向内执行.