【问题标题】:redux-observable epic chain dispatches duplicate actionsredux-observable 史诗链调度重复动作
【发布时间】:2018-01-20 18:24:00
【问题描述】:

传说

action-chain epic = Epic,根据服务调用返回“成功”或“失败”操作。 service = Http 服务,来自HttpModule,Angular2

目标

我需要向服务器发送数据。我有CREATECREATE_SUCCESSCREATE_FAIL 操作。我的想法是在提交时发送CREATE。然后我有一个action-chain epic,它启动service 调用我的服务器并根据响应触发CREATE_SUCCESSCREATE_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,此属性装饰了单个动作创建器函数并调度其返回值,即动作对象。这很奇怪,因为我同样称呼CREATECREATE_SUCCESS。这个装饰器是如何工作的?

编辑 4: 我已将行为范围缩小到:如果我从我的 Epic 中调用一个动作并且这个动作用@dispatch 装饰,它会被触发两次。我怀疑作为中间件的 Epic 在内部调度接收到的操作。如果我需要从我的容器组件手动调度一个动作,问题就来了。

解决办法

在杰菲尔普斯的帮助下。感谢您的答复。不过我喜欢 @dispatch 装饰,用于我的组件内部。我发现的一个个人解决方案是以starter-actions(从组件内部调度的那些)不会通过 Epic 调度的方式构建我的操作链。然后只需用@dispatch 装饰那些starter-actions 就可以了。

【问题讨论】:

  • 您的意思是每次 CREATE 都会触发两次操作吗?
  • @eenagy 是的,这就是我的意思。编辑更清晰。

标签: angular redux redux-observable


【解决方案1】:

提供的代码很好;看这里,只有一个CREATE_SUCCESShttps://jsbin.com/tagovok/edit?js,output

这表明问题出在此处未提供的代码中。我能想到的三种直接可能性:

  • 某处,不知何故,您正在调度两个 CREATE 操作(使用 redux devtools 来查看)
  • this.service.create(action.payload) 实际上发出 两个 东西而不是一个(使用 dodebuggers,或者你甚至可以在它之后添加一个 .take(1),如果可以解决它你知道)李>
  • 您将相同的史诗添加了两次,例如combineEpics(yourEpic, yourEpic)(这个很难确认。也许可以尝试在史诗 it 的初始调用中添加一个计数器,并确认它只会递增到 1,因为史诗函数本身只被调用一次)

根据你的更新:

我已将行为范围缩小到:如果我从 Epic 中调用一个动作并且该动作用 @dispatch() 修饰,它会被触发两次。我怀疑作为中间件的 Epic 在内部调度接收到的操作。如果我需要从我的容器组件手动调度一个动作,问题就来了。

redux-observable 确实会自动调度您的 Epics 发出的操作。我没有使用 angular-redux 的经验,但是这里有一些关于使用 redux-observable 的文档:https://github.com/angular-redux/store/blob/master/articles/epics.md

快速浏览一下,他们不使用史诗中的动作创建者,而只是使用 POJO。您仍然可以创建只返回 POJO 操作的操作创建器,just normal redux

【讨论】:

  • @alex 您可以尝试使用提供的帮助,如果仍然无法解决您的问题,那么我建议您使用缺少的详细信息更新您的答案
  • 感谢您的意见。我经历了这些想法,发现的唯一潜在问题是使用来自angular-redux/store@dispatch() 装饰器。我必须派出副本。我没有注册过多的史诗,我发送了单个 CREATE 动作(通过 Redux 开发工具确认)。我会尽量按常规方式派送。
  • 很高兴听到这个消息!
  • 我也面临同样的问题。我的 epic 分派 same action 两次。而在我的情况下,这只发生在我的 epictests 中。使用redux-dev-tools 调试我的应用程序仅显示一个已调度的操作。仅供参考,我正在 React 应用程序中使用 redux 商店。
  • @jayphelps 你能帮我解决我的问题吗?为什么我得到两个重复的操作?我应该为此问题创建一个单独的问题吗?
猜你喜欢
  • 2017-04-14
  • 2018-08-17
  • 1970-01-01
  • 2017-03-17
  • 2021-11-13
  • 2019-01-23
  • 2017-04-22
  • 1970-01-01
  • 2018-03-09
相关资源
最近更新 更多