在 redux 中集成 angular di 机制
最近一直在折腾 众所周知,angular是一个大而全的框架,想和redux一起使用,需要摒弃一些angular中常用的开发理念与模式,仅仅将它作为一个视图层框架使用,就和react一样,不在将类似 我们可以通过使用ng-redux注入redux服务,从而在angular中使用它。 基本的使用项目文档介绍的已经很详细了,这里仅仅想分享在这段时间折腾redux和angular遇到的一个比较蛋疼的问题,以及是如何解决的。 在redux中,业务逻辑的抽象被描述在action中,因此除了一些同步action以外,必然存在类似向后端发送请求获取数据之类的异步action。那么问题来了,在angular中有一个大家很熟悉的机制,叫作依赖注入(简称 那么我们如何来解决这个问题呢? 一种简单粗暴的方法就是,完全摒弃angular的di机制,使用外部的模块来解决问题。比如发请求,难道我们非要使用 这个问题费了我不少时间去搜索网上的资料,类似如何在action使用angular di机制,如果在action获取service实例等等,虽然能查到的资料都没有完美的给出解决方案,但是都把问题的解决方向,指向了同一处,即redux的中间件机制。 第二种方法则通过redux中间件的机制来实现
话虽然这么说,但是它是很有道理的,对于redux的中间件机制呢,它是对于action来设计的,即一个action,在最终转移到到处理它的reducer之前,会经过若干大大小小的中间件,这些中间件做的事情十分的简单,即输入一个action,按自己的处理逻辑加工它,再交到下一个中间件手中,直到没有下一个中间件为止。 明白了redux的中间件机制,那么上面的问题就好解决了,对于想在action中使用的通过angular di机制来实例化的服务,我们没有必要在action中实例化,我们完全可以仅仅在action中声明,之后呢,将实例化的过程交由中间件处理即可,那么可能你又会问,action没有办法集成di机制,中间件难道能集成吗,如果不能岂不是又回到了问题的原点?是的,但是中间件它的确可以集成di功能,为什么呢,因为中间件的实例化逻辑是通过ng-redux在angular内部进行的,而中间件本身呢,有仅仅是一个函数而已,那么我们完全可以把中间件的实现,声明成一个angular中的factory或者service,之后在其中使用angular的di机制,动态的实例化action中依赖服务的实例,关于这一点呢,在ng-redux的文档中有提及,但是没有说的特别的清楚。 talk is cheap,show me the code. 下面贴一下关于实现解决以上问题的中间件实现源码。 import angular from 'angular' import R from 'ramda' export default function thunkWithDepsMiddleware () { const injector = angular.element(document.body).injector() return ({dispatch,getState}) => next => action => { const isNotNil = R.complement(R.isNil) const isFSA = R.both(R.has('payload'),R.has('type')) const isLastItemIsFunction = R.compose(R.is(Function),R.last) const isAngularInlineArrayAnnotation = R.both(R.is(Array),isLastItemIsFunction) let annotation // FSA 处理逻辑 if (isFSA(action)) annotation = R.prop('payload',action) // 普通 action 处理逻辑 else annotation = action if (isAngularInlineArrayAnnotation(annotation)) { const locals = {dispatch: dispatch,getState: getState} const payload = injector.invoke(annotation,this,locals) if (isNotNil(payload)) return dispatch({...action,payload}) } else if (R.is(Function,annotation)) { const payload = annotation(dispatch,getState) if (isNotNil(payload)) return dispatch({...action,payload}) } else { return next(action) } } } 大体逻辑呢,就是通过angular中$injector服务来解决问题,抽离出action中的关于di的声明逻辑,该中间间仅支持 实现之后呢,通过ng-redux的语法注册它, $ngReduxProvider.createStoreWith(reducers,['thunkWithDepsMiddleware',promiseMiddleware]) 之后我们的action即可直接返回符合 export const fetchRoles = createAction(FETCH_ROLES,() => { return ['$q','dispatch',($q,dispatch) => { // do something ... }] }) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |