先来看看源码:
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))) }最后一行很难理解,把它换成function写法如下
funcs.reduce(function (a, b) { return function (...args) { return a(b(...args)) } })先看下reduce方法
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; // 从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。previousValue 上次循环的返回值
currentValue 当前循环item
所以第二次循环过程如下
// 第一次循环返回值为 function (...args) { return a(b(...args)) } // 第二次循环时,第一个参数为:第一次循环的返回值,第二个参数为:funcs 内第三个元素,用c来表示 // 第二次循环返回值为 function (...args) { return (function (...args) { return a(b(...args)) })(c(...args)) } // 整理后 function (...args) { return a(b(c(...args))) }所以 [a, b, c, d, e] 的执行结果是 (...args) => a(b(c(d(e(...args)))))。
所以能看出来,funcs 内函数需要满足 函数参数和函数返回值结构一致。
applyMiddleware
applyMiddleware 是把 dispatch 一层一层包装。洋葱圈模型。
先看看 createStore 的第三个参数 enhancer
function createStore(reducer, preloadedState, enhancer) { // 实现了 preloadedState 参数可以省略 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== 'undefined') { // 看起来 enhancer 是个高阶函数,返回值还是 store creator // 可以看出 enhancer 的大概结构为 // (createStore) => (reducer, preloadedState) => createStore(educer, preloadedState) return enhancer(createStore)(reducer, preloadedState) } // 这里是其他代码 // ... }再看看官网给的 applyMiddleware 使用例子
let store = createStore( todos, [ 'Use Redux' ], applyMiddleware(logger) )所以 applyMiddleware 的结构应该是
(...middlewares) => (createStore) => (reducer, preloadedState) => createStore(educer, preloadedState)所以猜出来了 applyMiddleware 的参数是函数,返回值执行多次后还是 createStore(educer, preloadedState)。
所以再来看官方定义就比较好理解
Middleware 可以让你包装 store 的 dispatch 方法来达到你想要的目的。同时, middleware 还拥有“可组合”这一关键特性。多个 middleware 可以被组合到一起使用,形成 middleware 链。其中,每个 middleware 都不需要关心链中它前后的 middleware 的任何信息。
来看 applyMiddleware 看源码, 跟着 序号看会稍微清晰点:
applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } // 2、chain内元素结构为 (store.dispatch) => store.dispatch // 所以 middleware(middlewareAPI) 结果为 (store.dispatch) => store.dispatch // 所以 middleware 结构为 (middlewareAPI) => (store.dispatch) => store.dispatch // 即 参数 middlewares 内元素结构为 (middlewareAPI) => (store.dispatch) => store.dispatch chain = middlewares.map(middleware => middleware(middlewareAPI)) // 1、上面解释过 compose 的返回值是 (...arg) => a(b(c(...arg))), // 所以下面 dispatch = ((...arg) => a(b(c(...arg))))(store.dispatch) // 即 dispatch = a(b(c(store.dispatch))) // 所以 a、b、c 即 chain内元素 的结构需要为 (store.dispatch) => store.dispatch dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch // 这里可以看出,applyMiddleware 只包装替换了 createStore 的 dispatch } } }现在我们知道了 applyMiddleware 的参数结构是 (middlewareAPI) => (store.dispatch) => store.dispatch,然后我们来写个简单的 middleware
// 原始长这个样子 function logger(middlewareAPI) { return (dispatch) => dispatch; } // 然后 给 dispatch 包装以下,并且换个名字叫 next function logger(middlewareAPI) { return (next) => (action) => { let value = next(action); return value; }; } // 然后 加入功能 function logger(middlewareAPI) { return (next) => (action) => { // 这里的 dispatch 是 createStore 创建的。一般不用。 const { getState, dispatch } = middlewareAPI; console.log('will dispatch', action); let value = next(action); console.log('state after dispatch', getState()); // createStore 里实现的 dispatch 返回 action, // 一般会是 action 本身,除非 // 后面的 middleware 修改了它。 return value; }; }