精益 React 学习指南 (Lean React)- 3.3 理解 redux 中间件
3.3 理解 Redux 中间件
这一小节会讲解 redux 中间件的原理,为下一节讲解 redux 异步 action 做铺垫,主要内容为:
3.3.1 Redux 中间件是什么
redux 提供了类似后端 Express 的中间件概念,本质的目的是提供第三方插件的模式,自定义拦截 3.3.2 使用 Redux 中间件Redux 提供了一个叫 import { createStore,applyMiddleware } from 'redux' import createLogger from 'redux-logger' import rootReducer from './reducers' const loggerMiddleware = createLogger() const initialState = {} return createStore( rootReducer,initialState,applyMiddleware( loggerMiddleware ) ) 3.3.3 logger 中间件结构分析看看 redux-logger 的源码结构 function createLogger(options = {}) { /** * 传入 applyMiddleWare 的函数 * @param {Function} { getState }) [description] * @return {[type]} [description] */ return ({ getState }) => (next) => (action) => { let returnedValue; const logEntry = {}; logEntry.prevState = stateTransformer(getState()); logEntry.action = action; // .... returnedValue = next(action); // .... logEntry.nextState = stateTransformer(getState()); // .... return returnedValue; }; } export default createLogger; Logger 中这样的结构 /** * getState 可以返回最新的应用 store 数据 */ function ({getState}) { /** * next 表示执行后续的中间件,中间件有可能有多个 */ return function (next) { /** * 中间件处理函数,参数为当前执行的 action */ return function (action) {...} } } 这样的结构本质上就是为了将 middleware 串联起来执行,为了分析 middleware 的执行顺序,还得看看 applyMiddleware 的实现 3.3.4 applyMiddleware 分析下面是 applyMiddleware 完整的代码,参数为 middlewares 数组: import compose from './compose' /** * Creates a store enhancer that applies middleware to the dispatch method * of the Redux store. This is handy for a variety of tasks,such as expressing * asynchronous actions in a concise manner,or logging every action payload. * * See `redux-thunk` package as an example of the Redux middleware. * * Because middleware is potentially asynchronous,this should be the first * store enhancer in the composition chain. * * Note that each middleware will be given the `dispatch` and `getState` functions * as named arguments. * * @param {...Function} middlewares The middleware chain to be applied. * @returns {Function} A store enhancer applying the middleware. */ export default function applyMiddleware(...middlewares) { return (createStore) => (reducer,preloadedState,enhancer) => { var store = createStore(reducer,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 } } }
所以关键点来到了 compose 方法了,下面来看一下 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)) } 可以看到 compose 方法实际上就是利用了 /** * [description] * @param {[type]} previousValue [前一个项] * @param {[type]} currentValue [当前项] */ [0,1,2,3,4].reduceRight(function(previousValue,currentValue,index,array) { return previousValue + currentValue; },10); 执行结果:
3.3.5 理解中间件的执行过程通过上面的 applyMiddleware 和 中间件的结构,假设应用了如下的中间件: [A,B,C],一个 action 的完整执行流程 初始化阶段一个中间件的结构为 function ({getState}) { return function (next) { return function (action) {...} } } 初始化阶段一:middlewares map 为新的 middlewares chain = middlewares.map(middleware => middleware(middlewareAPI)) 执行过后,middleware 变为了 function (next) { return function (action) {...} } 初始化阶段二:compose 新的 dispatch const newDispatch = compose(newMiddlewares)(store.dispatch) dispatch 的实现为 reduceRight,当一个新的 action 来了过后 /** * 1. 初始值为: lastMiddleware(store.dispatch) * 2. previousValue: composed * 3. currentValue: currentMiddleware * 4. return value: currentMiddleware(composed) => newComposed */ rest.reduceRight((composed,last(...args)) composed 流程reduceRight 的执行过程: 初始时候
第一次执行:
第二次执行:
最后的返回结果为 执行阶段
整个执行 action 的过程为 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |