我有一个带有四个ngrx动作的Angular(2)应用程序:
-
开始
-
未由reducer处理(无状态更改)
-
ngrx Effect调用异步任务并映射到SUCCESS或ERROR
-
成功
-
由reducer处理
-
ngrx效果映射到ADVANCE
-
ADVANCE
-
不由reducer处理
-
ngrx效果导航到其他路线
-
错误
-
由reducer处理
-
无效果
The problem is that the Effect that catches ADVANCE seems to run before the reducer that processes SUCCESS
这是效果代码:
@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]));
我得到的错误是 Cannot read property 'bar' of null
. 属性 foo
由处理SUCCESS的reducer设置 .
If I add a delay to the SUCCESS effect, it all works nicely:
@Effect() success$ = this.actions$
.ofType('SUCCESS')
.delay(1)
.map(() => ({type: 'ADVANCE'}));
但是不得不加上这个延迟对我来说没有意义 .
我在各处添加了 console.log
语句,输出如下所示:
-
成功效果
-
ADVANCE效果(显示route.foo === null)
-
SUCCESS reducer(显示route.foo ===的东西)
-
错误
我期望SUCCESS效果和SUCCESS减速器在ADVANCE效果之前运行 .
Am I doing something wrong?
Is it incorrect to expect that actions are processed by the reducers in the same order that they are dispatched?
版本:
-
@ angular / cli:1.0.0-beta.32.3
-
node:7.5.0
-
os:darwin x64
-
@ angular / common:2.4.7
-
@ angular / compiler:2.4.7
-
@ angular / core:2.4.7
-
@ angular / forms:2.4.7
-
@ angular / http:2.4.7
-
@ angular / platform-browser:2.4.7
-
@ angular / platform-browser-dynamic:2.4.7
-
@ angular / router:3.4.7
-
@ angular / cli:1.0.0-beta.32.3
-
@ angular / compiler-cli:2.4.7
-
@ ngrx / core @ 1.2.0
-
@ ngrx / effects @ 2.0.0
-
@ ngrx / store @ 2.2.1
-
rxjs:5.1.1
3 回答
使用.concatMap替换START操作的catch中的.map可能会有效,并将 Map 放到SUCCESS和ACTION那里 .
ngex / effects的目的是充当基于redux的环境中的中间件 .
所以你在这里所做的就是调用“成功”动作,它应该同时适用于reducer并继续执行另一个动作就是中间件 . 但这是有效的辅音,它应该拦截动作并自己处理它们,只有异步处理它才会发送动作 .
那么这里发生了什么?你将成功发送到两个不同的地方,一个应该由reducer处理,一个应该由中间件处理 . 我不确定它是否总是那样,但是中间件会在它击中减速器之前拦截进来的动作 . 我认为,如果你稍微修改一下你的代码,它应该可行 . 尝试做类似的事情:
你看到我在这做什么?我已经删除了拦截“成功”的中间件,所以“成功”不会击中减速器 . 在它之后,它会发出另一个“提前”类型的动作,它应该在“成功”完成后处理你的中间件 .
希望能帮助到你 .
回答你的结论性问题:
似乎有一个导致此行为的错误 . 您很可能正在体验它,因为您直接映射到另一个操作 . 通常,如果您有异步操作或类似的操作,则reducer在听取下一个操作的效果开始之前有时间完成 .
也许不是您问题的一部分,但是您指定问题的解决方案是在您的有效负载的帮助下直接在SUCCESS中导航到您的新路由,或者将有效负载传递给ADVANCE .
以下链接是与您相关的效果,存储和rxjs项目中报告的问题:
https://github.com/ngrx/effects/issues/58
https://github.com/ngrx/store/issues/279
/ ReactiveX / rxjs / issues / 2155(链接到这个的名声太少)
好像他们正在努力:)