标签:das pre cti 个人 影响 es6 很多 控制 state
以上是整理的一些说明和文档资料,没有看过的可以去了解一下。下面将开始本文的主题:redux的中间件applyMiddleware。
都说名字越长,越让学者害怕,applyMiddleware的名字看起来就挺吓人,那么为什么会出现中间件,它是做什么的?它为什么叫中间件?为什么说可以用来解决异步dispatch?经过一段时间的了解,让我渐渐明白了它的工作原理,现在让我们带问题,怀着简单,轻松的心态走进applyMiddleware大讲堂:
console.log(‘dispatching‘, action);
dispatch(action)
假如又来一个产品B说,我需要记录每次数据出错的原因,我们怎么办呢?然后我们又需要在对每一个dispatch做修改
try{ dispatch(action) }catch(err){ console.error(‘错误报告: ‘, err) }
如果我们的程序中有很多的dispatch,我们就需要添加很多的重复代码,虽然编辑器提供批量替换,但这无疑是产生了很多样板代码。
因为所有的需求都是和dispatch息息相关,所以只要我们把日志放进dispatch函数里,不就好了吗,我们只需要更改dispatch函数,把dispatch进行一层封装。
大概的封装就是下面这样:
let next = store.dispatch store.dispatch = function dispatchAndLog(action) { console.log(‘dispatching‘, action) next(action) }
Redux把这个封装的入口写成了一个函数,就叫applyMiddleware。
由此我们明白了applyMiddleware的功能:改造dispatch函数,产生真假dispatch,而中间件就是运行在假真(dispatchAndLog假和next真)之间的代码。
这里我们要对applyMiddleware进行一个准确的定义,它只是一个用来加工dispatch的工厂,而要加工什么样的dispatch出来,则需要我们传入对应的中间件函数(比如上例中的dispatchAndLog),下面我们构造一个精简版的applyMiddleware:
const applyMiddleware = function(middleware){ let next = store.dispatch; store.dispatch = middleware(store)(next); // 这里传入store,是因为中间件中有可能会用到getState获取数据,比如打印当前用户等需求 } applyMiddleware(dispatchAndLog)
const logger = store => next => action => { console.log(‘dispatching‘, action) return next(action) } const collectError = store => next => action => { try { return next(action) } catch (err) { console.error(‘Error!‘, err) } }
然后,我们改造一下applyMiddleware,来接收一个middlewares数组:
function applyMiddleware(middlewares) { middlewares = middlewares.slice() middlewares.reverse() let dispatch = store.dispatch middlewares.forEach(middleware => dispatch = middleware(store)(dispatch) ) return Object.assign({}, store, { dispatch }) }
上面的middleware(store)(dispatch) 就相当于是 const logger = store => next => {},这就是构造后的dispatch,继续向下传递。这里middlewares.reverse(),进行数组反转的原因,是最后构造的dispatch,实际上是最先执行的。因为在applyMiddleware串联的时候,每个中间件只是返回一个新的dispatch函数给下一个中间件,实际上这个dispatch并不会执行。只有当我们在程序中通过store.dispatch(action),真正派发的时候,才会执行。而此时的dispatch是最后一个中间件返回的包装函数。然后依次向前递推执行。
我们拿logger和collectError来说明:
构造过程:
let next = store.dispatch; let dispatch1 = logger(store)(next); // 这时候的console.log(‘dispatching‘, action) 是没有执行的 let dispatch2 = collectError(store)(dispatch1); // 这时候的console.log(‘Error!‘, err) 也是没有执行的 store.dispatch = dispatch2;
执行过程:
store.dispatch(action); //假如我们程序中派发了某个action //相当于是下面这样 dispatch2(action); //此时执行了 console.log(‘Error‘, err) //由于collectError中间件中的next是接收的logger返回函数即dispatch1,所以在开始执行 dispatch1(action); //此时执行了 console.log(‘dispatching‘, action) // 这个例子不太合理,因为错误报告是先 try 的 next(action),但是正常的流程是如此。
未完待续……
标签:das pre cti 个人 影响 es6 很多 控制 state
原文地址:http://www.cnblogs.com/wshiqtb/p/7909770.html