Angular ngrx效果:由一个效果发送的动作是否立即由其他效果处理?
我有一个有四个ngrx动作的角度(2)应用程序:Angular ngrx效果:由一个效果发送的动作是否立即由其他效果处理?,angular,ngrx,ngrx-effects,Angular,Ngrx,Ngrx Effects,我有一个有四个ngrx动作的角度(2)应用程序: 开始 减速器未处理(无状态变化) ngrx效应调用异步任务并映射到成功或错误 成功 由减速机加工 ngrx效果图向前进 前进 未经减速机加工 ngrx效果导航到不同的路线 错误 由减速机加工 无效 问题是,捕捉前进的效果似乎先于处理成功的减速器运行 以下是效果代码: @Effect() start$ = this.actions$ .ofType('START') .map(toPayload) .sw
- 开始
- 减速器未处理(无状态变化)
- ngrx效应调用异步任务并映射到成功或错误
- 成功
- 由减速机加工
- ngrx效果图向前进
- 前进
- 未经减速机加工
- ngrx效果导航到不同的路线
- 错误
- 由减速机加工
- 无效
@Effect() start$ = this.actions$
.ofType('START')
.map(toPayload)
.switchMap(input => doAsyncTask(input)
.map(result => ({type: 'SUCCESS', payload: result}))
.catch(error => ({type: 'ERROR', payload: error})));
@Effect() success$ = this.actions$
.ofType('SUCCESS')
.map(() => ({type: 'ADVANCE'}));
@Effect({dispatch: false}) advance$ = this.actions$
.ofType('ADVANCE')
.withLatestFrom(this.store$.select(state => state.route))
.map(action_route => action_route[1])
.do(route => this.router.navigate([route.foo.bar]));
我得到的错误是无法读取null的属性“bar”
。属性foo
由处理成功的减速器设置
如果我为成功效果添加延迟,一切都会很好地工作:
@Effect() success$ = this.actions$
.ofType('SUCCESS')
.delay(1)
.map(() => ({type: 'ADVANCE'}));
但是不得不加上这个延迟对我来说没有意义
我在所有地方添加了console.log
语句,输出如下:
版本:
- @angular/cli:1.0.0-beta.32.3
- 节点:7.5.0
- os:Darwinx64
- @角度/普通:2.4.7
- @角度/编译器:2.4.7
- @角度/核心:2.4.7
- @角度/形状:2.4.7
- @angular/http:2.4.7
- @角度/平台浏览器:2.4.7
- @角度/平台浏览器动态:2.4.7
- @角度/路由器:3.4.7
- @angular/cli:1.0.0-beta.32.3
- @角度/编译器cli:2.4.7
- @ngrx/core@1.2.0
- @ngrx/effects@2.0.0
- @ngrx/store@2.2.1
- rxjs:5.1.1
@Effect() start$ = this.actions$
.ofType('START')
.map(toPayload)
.switchMap(input => doAsyncTask(input)
.map(result =>{
this.store$.dispatch(
{type: 'SUCCESS',
payload: result
});
this.store$.dispatch(
{type: 'ADVANCE'})
}
.catch(error => ({type: 'ERROR', payload: error})));
你知道我在这里做什么吗?我已经删除了拦截“成功”的中间件,因此“成功”不会击中减速机。紧接着,它会发送另一个类型为“advance”的动作,在“成功”处理完成后,该动作会击中您的中间件
希望对你有帮助 用.concatMap替换开始操作捕获中的.map,并将您的成功地图和行动地图都放在那里,可能会奏效
@Effect() start$ = this.actions$
.ofType('START')
.map(toPayload)
.switchMap(input => doAsyncTask(input)
.concatMap(result => {
return Observable.from([type: 'SUCCESS', payload: result,
type: 'ADVANCE'])
.catch(error => ({type: 'ERROR', payload: error})));
回答您的结论性问题:
- 我做错什么了吗
- 不,我不认为你做错了什么
- 期望减缩器按照调度操作的相同顺序处理操作是否不正确
- 这样的顺序似乎是合乎逻辑的,但显然你现在不能期望这样
- /ReactiveX/rxjs/issues/2155(声誉太低,无法与此链接)
看起来他们正在研究:)您使用的是什么版本?通过类似的安排,我看到减速器在效果之前处理动作。@cartant-我在问题中添加了版本。谢谢您的检查。我的
@ngrx
版本是相同的。你的RxJS版本怎么样?我的是5.2.0。您可能还希望在问题中包括您的NgModule
引导。存储(通过reducer manager)和可观察到的效果动作都订阅了dispatcher。听起来你的特效好像在商店前订阅了调度器。@cartant-我有rxjs 5.1.1。我昨天花了好几个小时调试这个,结果一无所获。我今天还要多花点时间。谢谢你,吉莉。我不确定是否在有效期内调用this.store$.dispatch
。我看不出它有什么根本性的错误,但我认为它应该是不必要的,因为效果能够将一个动作映射到另一个动作。现在,你确定ngrx特效会在操作到达减缩器之前拦截它们吗?这是关于中间件的redux官方文档-。这是我转述的一句话,“它提供了一个第三方扩展点,从发送一个动作到它到达减速机的那一刻。”我在我的项目中也使用了redux和effects,我根据自己的理解和经验回答。我之所以不将两个动作映射为一个动作,是因为我希望完全控制它们将被处理的顺序。没有必要这样做