乐趣区

关于前端:miniredux-实现原理讲解-第四讲

文章首发于我的博客 https://github.com/mcuking/bl…

相干代码请查阅 https://github.com/mcuking/bl…

接着上一讲的中间件机制持续讲。
上一讲中咱们实现了 redux-thunk 中间件,使得加强后的 dispatch 不仅可能接管对象类型的 action,还可能接管函数类型的 action。
在此咱们是否可能在结构一个中间件,使得加强后的 dispatch 还能解决 action 组成的数组,如下:

export function buyHouse() {return {type: BUY_House}
}

export function buyHouseAsync() {
    return dispatch => {setTimeout(() => {dispatch(buyHouse())
        }, 2000)
    }
}

export function buyTwice() {return [buyHouse(), buyHouseAsync()]
}

结构中间件 redux-arrThunk

为此咱们决定再结构一个中间件,命名 redux-arrThunk,使加强后的 dispatch 还能解决 action 组成的数组。代码如下:

const arrThunk = ({dispatch, getState}) => next => action => {
    // next 为原生的 dispatch
    // 如果是数组,顺次执行数组中每一个 action,参数是 dispatch 和 getState
    if (Array.isArray(action)) {return action.forEach(v=>dispatch(v))
    }
    // 如果不满足条件,则间接调用下一个中间件(应用 next)// 如果满足条件,则须要从新 dispatch(调用 dispatch)// 默认间接用原生 dispatch 收回 action
    return next(action)
}

中间件叠加应用

因为原理相似第三讲中的 redux-thunk,下面的代码并不难,但问题是,咱们如何将这两个中间件叠加起来应用,为此咱们须要批改之前的 applyMiddleware 函数,使其可能接管多个中间件,并且是的这些中间件可能叠加应用。代码如下:

// applyMiddleware
export function applyMiddleware(...middlewares) {return createStore => (...args) => {
        // 第一步 取得原生 store 以及原生 dispatch
        const store = createStore(...args)
        let dispatch = store.dispatch
        
        const midApi = {
            getState: store.getState,
            dispatch: (...args) => dispatch(...args)
        }
        // 第二步 将原生 dipatch 传入中间件进行扩大加强,生成新的 dispatch
        const middlewaresChain = middlewares.map(middleware => middleware(midApi))
        dispatch = compose(...middlewaresChain)(dispatch)
        // dispatch = middleware(midApi)(dispatch)
        return {
            ...store, // 原生 store
            dispatch, // 加强扩大后的 dispatch
        }
    }
}


// compose
//compose(fn1, fn2, fn3) return 为 fn1(fn2(fn3))
export function compose(...funcs) {if (funcs.length === 0) {return arg => arg}
    if (funcs.length === 1) {return funcs[0]
    }
    return funcs.reduce((ret, item) => (...args) => ret(item(...args)))
}

比照上一讲中的 applyMiddleware,这一次次要是在解决中间件时,对中间件进行了遍历,并且通过 compose 办法使得多个中间件能够叠加应用,行将 fn1, fn2, fn3 转换为 fn1(fn2(fn3))

// 之前
dispatch = middleware(midApi)(dispatch)

// 之后
const middlewaresChain = middlewares.map(middleware => middleware(midApi))
dispatch = compose(...middlewaresChain)(dispatch)

因而能够像如下代码一样进行叠加应用多个中间件

import React from 'react'
import ReactDOM from 'react-dom'
import {createStore, applyMiddleware} from './mini-redux'
import {Provider} from './mini-react-redux'
import {counter} from './index.redux'
import thunk from './mini-redux-thunk'
import arrThunk from './mini-redux-arrThunk'
import App from './App'

const store = createStore(counter, applyMiddleware(thunk, arrThunk))

ReactDOM.render(
    (<Provider store={store}>
            <App/>
        </Provider>
    ),
    document.getElementById('root')
)

其中 const store = createStore(counter, applyMiddleware(thunk, arrThunk)),意味着加强后的 dispatch 具备如下性能

dispatch(action) = thunk(arrThunk(midApi)(store.dispatch)(action))

至此,咱们的 mini-redux 就开发实现咯,有任何问题或意见欢送分割我。

相干文章如下:

  • mini-redux 实现原理解说 第一讲
  • mini-redux 实现原理解说 第二讲
  • mini-redux 实现原理解说 第三讲
  • mini-redux 实现原理解说 第四讲
退出移动版