传说action-chain epic
=epic,根据服务调用返回“成功”或“失败”操作。service
=http服务,来自HttpModule
,angular2
目标
我需要把数据发送到服务器。我有一个CREATE
,CREATE_SUCCESS
和CREATE_FAIL
动作。我的想法是在提交时发送CREATE
。然后我有一个action-chain epic
,它启动对服务器的service
调用,并根据响应触发CREATE_SUCCESS
或CREATE_FAIL
。
问题
myaction-chain epic
触发重复动作-在这两种情况下,它都会触发两个动作,例如:如果成功,对于每个CREATE
它都会发送两个CREATE_SUCCESS
动作。
代码
private createAnimalActionChain() {
return action$ => {
return action$
.ofType(AnimalActions.CREATE)
.switchMap(action => {
return this.service
.create(action.payload)
.map(httpResponse => {
let response = httpResponse.json()
if (response.success) {
return this.actions.createSuccess()
}
return this.actions.createFail(response.errors)
})
})
}
}
这就是我写的,而且大部分都在起作用。如果有更好的办法,我洗耳恭听。派遣多个行动直到最近才是真正的问题,但它似乎从来没有对我没问题,所以我很想解决它。
编辑:我刚刚发现,有时我的应用程序会在执行任何epic之前发送重复的操作。我现在想知道为什么。
编辑2:无需编辑。这是一个孤立的案例,submit事件一直冒泡到顶部,因为我将我的
@Output()
字段命名为“submit”-它导致了双重动作分派。现在已修复,与上述史诗问题无关。它仍然存在。编辑3:在@jayphelps的帮助下,我能够跟踪这个问题。结果我的行动,从史诗的链条,触发了两次。但我不知道为什么会这样。这是我的旧密码:
static CREATE = 'CREATE'
static CREATE_SUCCESS = 'CREATE_SUCCESS'
static CREATE_FAIL = 'CREATE_FAIL'
@dispatch()
create = (animal: IAnimal) => ({
type: AnimalActions.CREATE,
payload: animal
})
@dispatch()
createSuccess = () => ({
type: AnimalActions.CREATE_SUCCESS
})
@dispatch()
createFail = (errors: object) => ({
type: AnimalActions.CREATE_FAIL,
payload: errors
})
此代码发送
CREATE
一次,CREATE_SUCCESS
两次和CREATE_FAIL
两次。我删除了最后两个装饰:static CREATE = 'CREATE'
static CREATE_SUCCESS = 'CREATE_SUCCESS'
static CREATE_FAIL = 'CREATE_FAIL'
@dispatch()
create = (animal: IAnimal) => ({
type: AnimalActions.CREATE,
payload: animal
})
createSuccess = () => ({
type: AnimalActions.CREATE_SUCCESS
})
createFail = (errors: object) => ({
type: AnimalActions.CREATE_FAIL,
payload: errors
})
这个代码看起来工作正常,每个操作只触发一个。我很困惑为什么这样做。根据API docs这个属性修饰单个action creator函数并分派其返回值action对象。这很奇怪,因为我对
@dispatch()
和CREATE
的调用是相同的。这个装潢师是怎么工作的?编辑4:
我已经将行为缩小到这个范围:如果我从我的史诗中调用一个动作,并且这个动作用
CREATE_SUCCESS
修饰,它将被触发两次。我怀疑epic作为一个中间件在内部发送接收到的操作。如果需要从容器组件手动分派操作,问题就来了。解决方案
在Jayphelps的帮助下。谢谢你的回复。不过,我喜欢
@dispatch
装饰,用于我的组件内部。我发现的一个前个人解决方案是以一种方式构建我的动作链,这种方式@dispatch
(从组件内部发送的)不会通过epic发送。然后用starter-actions
装饰那些starter-actions
就行了。 最佳答案
提供的代码很好;请看这里,只有一个CREATE_SUCCESS
:https://jsbin.com/tagovok/edit?js,output
这表明问题出在这里没有提供的代码中。我能想到三种可能:
在某个地方,不知怎的,您正在分派两个CREATE
操作(使用redux devtools查看)this.service.create(action.payload)
实际上会发射两个东西而不是一个(使用do
,debugger
s,或者你甚至可以在它之后添加一个.take(1)
,如果它修复了你知道的)
您已经添加了两次同一史诗,例如combineEpics(yourEpic, yourEpic)
(这一次很难确认。可能尝试在epic it的初始调用中添加一个计数器,并确认它只被递增到1,因为epic函数本身只被调用过一次)
基于您的更新:
我已经将行为缩小到这个范围:如果我从我的史诗中调用一个操作,并且这个操作用@dispatch()修饰,那么它将被触发两次。我怀疑epic作为一个中间件在内部发送接收到的操作。如果需要从容器组件手动分派操作,问题就来了。
事实上,redux observate会自动分派epics发出的操作。我没有使用角红字的经验,但是这里有一些关于使用它的文档:https://github.com/angular-redux/store/blob/master/articles/epics.md
快速浏览一下就可以发现,他们并不使用史诗中的动作创造者,而只是使用pojo。您仍然可以创建只返回pojo操作的操作创建者,just normal redux。