最近项目前端开发框架采用React+Redux进行实现,但是,如何异步访问服务器端,以及想要在开发过程中进行状态树日志的输出,所以怎么才能解决这两个问题? 采用Redux中间件
为什么要使用中间件
在利用Redux进行状态管理时,用户在UI层面触发行为,一个action对象通过store.dispatch派发到Reducer进行触发,接下来Reducer会根据type来更新对应的Store上的状态树,更改后的state会触发对应组件的重新渲染。如下图所示。在这个流程中,action对象是一个同步的对象,是一个包含type字段的简单对象,但是在访问服务器时,由于浏览器是单线程的,不会一遍渲染组件一遍等待服务器返回的结果,因此我们需要设计一种异步访问服务器的方法来实现与服务器端的正常通信。
中间件介绍
在Redux架构下,一个action对象在通过store.dispatch派发,在调用reducer函数前,会先经过一个中间件环节,如下图所示。
从上图可以看出,在一个Redux架构中可以用多个中间件,这些中间件一起组织处理请求的“管道”。一个中间件是一个独立的函数,可以组合使用,中间件有一个统一的接口,正因为一个中间件只能完成一个特定的功能,所以把多个中间件组合在一起才能满足比较丰富的应用需求。当然在使用时,也需要按照顺序依次处理传入的action,只有排在前面的中间件完成任务之后,后面的中间件才能有机会继续处理action。
中间件的特点
中间件是独立的函数
中间件可以组合使用
中间件有一个统一的接口
中间件接口
每个中间件必须定义为一个函数,返回一个接受next参数的函数,而这个接受next参数的函数又返回一个接受action参数的函数。next参数本身也是一个函数,中间件调用这个next函数通知Redux自己的处理工作已经结束。
一个什么都不做的中间件代码如下:
function doNothingMiddleware({dispatch, getState}) { return function(next){ return function(action){ return next(action); } } }
包含的功能有:
调用dispatch派发出一个新的action对象
调用getState获得当前Redux Store上的状态
调用next告诉Redux当前中间件工作完毕,让Redux调用下一个中间件
访问action对象action上的所有数据
在一个Redux应用如果想要使用中间件,必须通过applyMiddleware来生成。Redux的源码文件非常简单,由五个文件一起组成,分别是createStore.js,applyMiddlware.js,compose.js,bindActionCreator.js,combineReducers.js。与createStore是用来创建一个状态树,并且暴露出几个方法,包括dispatch,subscribe,getState,replaceReducer和$$observable,给createStore传入的参数有reducer,preloadedState和enhancer,其中enhancer就是一个store增强器,是一个函数,只能用applyMiddleware生成。applyMiddleware函数是根据外部函数(中间件函数)包装原来的dispatch函数,然后将新的dispatch函数暴露出去。
//根据外部函数(中间件函数)包装原来的dispatch函数,然后将新的dispatch函数暴露了出去 export default function applyMiddleware(...middlewares) { //return一个函数,它可以接受createStore方法作为参数,给返回的store的dispatch方法再进行一次包装 return createStore => (...args) => {//agrs包含reducer, preloadedState, enhancer const store = createStore(...args) let dispatch = () => { throw new Error( `Dispatching while constructing your middleware is not allowed. ` + `Other middleware would not be applied to this dispatch.` ) } //暴露两个方法给外部函数 const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) } //传入middlewareAPI参数并执行每一个外部函数,返回结果汇聚成数组 const chain = middlewares.map(middleware => middleware(middlewareAPI)) //这里用到了compose方法 dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
中间件与增强器的区别
中间件和增强器都是对Redux Store的增强,但是中间件仅仅是对Redux Store的dispatch方法进行了增强,也就是从dispatch函数调用到action对象被reducer处理这个过程中的操作,增强器是对Redux Store进行更深层次的增强定制,需要使用Store Enhancer,通过阅读增强器接口,一个增强器其实利用随给的参数创造出一个store对象,然后定制对象,最后把Store对象返回。总的对比如下:
中间件: 可以用来增强redux store的dispatch函数,也就是从dispatch函数调用到action对象被reducer处理这个过程中的操作
增强器: 对redux store进行更深层次的增强定制,可以增强redux store的各个方面。
异步访问服务器:
异步action对象