代码之家  ›  专栏  ›  技术社区  ›  Alex

redux可观察epic链调度重复动作

  •  3
  • Alex  · 技术社区  · 8 年前

    action-chain epic =Epic,根据服务调用返回“成功”或“失败”操作。 service HttpModule ,角度2

    目标

    我需要将数据发送到服务器。我有一个 CREATE , CREATE_SUCCESS CREATE_FAIL 行动。我的想法是 动作链史诗 ,开始 呼叫我的服务器并激发 创建_成功 CREATE_失败 取决于响应。

    我的 动作链史诗 触发重复操作-在这两种情况下,它触发两个操作,例如:在成功的情况下,为每个 创建 它发送了两个 行动。

     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)
                            })
                    })
            }
        }
    

    编辑

    :Nevermind 编辑 .这是一个孤立的案例,提交事件一直冒泡到顶部,因为我将我的 @Output() 字段“submit”-它导致双重动作调度。它现在已修复,与上述Epic问题无关。它仍然存在。

    :在@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_失败 @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 此属性装饰单个动作创建者函数,并分派其返回值,即动作对象。这很奇怪,因为我打电话 完全相同。这个装饰师是怎么工作的?

    编辑4 : @dispatch ,触发两次。我怀疑Epic作为一个中间件在内部调度接收到的操作。如果需要从容器组件手动调度操作,问题就来了。

    解决方案

    在JayPhels的帮助下。谢谢你的回复。但是我喜欢 装饰,用于我的组件内部。我找到的一个解决方案是以一种方式构建我的行动链 starter-actions (那些从组件内部调度的)不会通过Epic进行调度。那就装饰一下 具有 @调度

    1 回复  |  直到 5 年前
        1
  •  5
  •   jayphelps    8 年前

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

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

    • CREATE 操作(使用redux开发工具查看)
    • this.service.create(action.payload) 实际发射 do , debugger s、 或者你甚至可以添加一个 .take(1)
    • 您将同一史诗添加了两次,例如。 combineEpics(yourEpic, yourEpic) (这个很难确认。也许可以尝试在epic it的初始调用中添加一个计数器,并确认它只会增加到1,因为epic函数本身只调用过一次)

    基于您的更新:

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

    https://github.com/angular-redux/store/blob/master/articles/epics.md

    just normal redux .