Redux学习之一:何为middleware?
接触到redux有半个月之久了,最初是被各种概念绕的云里雾里,但是最近自己实现了一个demo之后,才发现redux是如此简洁,简洁到源代码就五部分组成,最大的createStore.js也就151行代码而已。 createStore.js applyMiddleware.js bindActionCreators.js combineReducers.js compose.js redux的魅力在于其简洁和FP编程思想。像reducers的设计、curry编程风格等都散发出淡淡的FP的味道。 1.什么是middleware?学过nodejs的人对middleware一定不会陌生。在nodejs里面,middleware是req和res之间的中间层,可以做很多事情。但在redux里面,middleware又是什么呢。
不难理解,在redux里,middleware是发送action和action到达reducer之间的第三方扩展,也就是中间层。也可以这样说,middleware是架在action和store之间的一座桥梁。 2.为什么要引入middleware?也许有人会问,到底middleware有什么用?
同步的情况下一切都很完美…… var asyncSayActionCreator = function (message) { setTimeout(function () { return { type: 'SAY',message } },2000) } 这会报错,因为这个asyncSayActionCreator返回的不是一个action,而是一个function。这个返回值无法被reducer识别。 3.middleware如何工作?我们看看redux-thunk的代码: export default function thunkMiddleware({ dispatch,getState }) { return next => action => typeof action === 'function' ? action(dispatch,getState) : next(action); } 仅仅是区区的6行代码,以至于我第一次看代码的时候怀疑是不是看错了,但其实它就这么简单。一个三目符,如果action是一个函数,执行这个action函数,如果不是函数,执行next函数。 const finalCreateStore=applyMiddleware(thunkMiddleware)(createStore) const store = finalCreateStore(reducer) 这就是我们最常使用middleware的代码。把源码中的next换成createStore,如果action是一个函数(这里的action是改造后的ActionCreator),便会执行这个action(dispatch,getState)函数。 var asyncSayActionCreator = function (message) { return function (dispatch) { setTimeout(function () { dispatch({ type: 'SAY',message }) },2000) } } 这里的action是return的函数: function (dispatch) { setTimeout(function () { dispatch({ type: 'SAY',2000) } 如果action返回的不是函数,即返回的是action对象的话,执行createStore函数的dispatch方法。
4.applyMiddleware都做了什么?redux2.0对applyMiddleware做了柯里化处理。 import compose from './compose'; export default function applyMiddleware(...middlewares) { return (next) => (reducer,initialState) => { var store = next(reducer,initialState); 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 }; }; } 其实最核心的代码也就是下面两句: chain = middlewares.map(middleware => middleware(middlewareAPI)); dispatch = compose(...chain)(store.dispatch); 前一句是执行middlewares数组里的每一个中间件,下一句是将chain柯里化,合成一个函数。 5.自己的middleware怎么写?学了这些,我们可以自己写一个middleware练练手。 export default function callTraceMiddleware ({dispatch,getState}){ return next=> action =>{ console.trace(); return next(action); } } 然后在调用中间件部分添加中间件: const createStoreWithMiddleware = applyMiddleware( thunkMiddleware,loggerMiddleware,callTraceMiddleware )(createStore); 这样我们运行在浏览器窗口就可以看到打印的函数调用轨迹。是不是很简单…… 总结redux的middleware是对action进行扩展处理,这样丰富了应用需求。以上是我对redux的个人理解,如发现错误恳请批评指正。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |