一句话总结,Middleware 就是增强了 dispatch
- //调用
- 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,可以传入多个中间件
- 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)
-
- 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))) 翻译一下
所以最后返回的 dispatch 是经过处理的 dispatch:a(b(c(d(e(f(store.dispatch)))
- //以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
- }
- }
-
- //模拟三个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,然后由外向内执行。