【发布时间】:2018-01-20 18:24:00
【问题描述】:
传说
action-chain epic = Epic,根据服务调用返回“成功”或“失败”操作。
service = Http 服务,来自HttpModule,Angular2
目标
我需要向服务器发送数据。我有CREATE、CREATE_SUCCESS 和CREATE_FAIL 操作。我的想法是在提交时发送CREATE。然后我有一个action-chain epic,它启动service 调用我的服务器并根据响应触发CREATE_SUCCESS 或CREATE_FAIL。
问题
我的action-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 之前调度重复的操作。我现在正试图了解原因。
EDIT 2:没关系EDIT。这是一个孤立的案例,提交事件一直冒泡到顶部,并且因为我将我的 @Output() 字段命名为“提交” - 它导致了双重操作调度。它现在已修复,与上述 Epic 问题无关。它仍然存在。
编辑 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 两次。我删除了最后两个 @dispatch() 装饰器:
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,此属性装饰了单个动作创建器函数并调度其返回值,即动作对象。这很奇怪,因为我同样称呼CREATE 和CREATE_SUCCESS。这个装饰器是如何工作的?
编辑 4:
我已将行为范围缩小到:如果我从我的 Epic 中调用一个动作并且这个动作用@dispatch 装饰,它会被触发两次。我怀疑作为中间件的 Epic 在内部调度接收到的操作。如果我需要从我的容器组件手动调度一个动作,问题就来了。
解决办法
在杰菲尔普斯的帮助下。感谢您的答复。不过我喜欢 @dispatch 装饰,用于我的组件内部。我发现的一个个人解决方案是以starter-actions(从组件内部调度的那些)不会通过 Epic 调度的方式构建我的操作链。然后只需用@dispatch 装饰那些starter-actions 就可以了。
【问题讨论】:
-
您的意思是每次 CREATE 都会触发两次操作吗?
-
@eenagy 是的,这就是我的意思。编辑更清晰。
标签: angular redux redux-observable