【问题标题】:Stuck in endless loop when not dispatching an action in ngrx/effects未在 ngrx/effects 中调度动作时陷入无限循环
【发布时间】:2017-01-01 18:58:09
【问题描述】:

我正在使用 Angular2 和 ngrx/store 和 ngrx/effects 进行状态管理。

当某个操作失败时,我想显示一条错误消息,但似乎我无法在 @Effects() 块中执行此任务。请参阅以下内容:

  @Effect() selectOfficeFail$ = this.actions$
   .ofType(SelectOfficeActions.LOAD_FAIL)
   .do(() => {
     alert('Error! No offices found!'); // I keep entering here
  });

当上面的代码运行时,警报会运行无数次,直到浏览器崩溃。似乎@Effect() 必须返回一个新的dispatch(),但我不明白为什么。为什么上面的 alert() 会运行无数次?

编辑:不会多次发送SelectOfficeActions.LOAD_FAIL。只有一次

【问题讨论】:

    标签: angular ngrx


    【解决方案1】:

    是的,您是对的,@effect 需要调度一个新操作,但我认为您的应用程序逻辑有问题。

    您不应该在组件或服务中调度 SelectOfficeActions.LOAD_FAIL 操作,而是调用 @Effect 的 LOAD 操作,然后效果会根据条件依次调度 LOAD_COMPLETELOAD_FAIL

    类似 example 的东西来自 github 库

     @Effect() login$ = this.updates$
          // Listen for the 'LOGIN' action
          .whenAction('LOGIN')
          // Map the payload into JSON to use as the request body
          .map(update => JSON.stringify(update.action.payload))
          .switchMap(payload => this.http.post('/auth', payload)
            // If successful, dispatch success action with result
            .map(res => ({ type: 'LOGIN_SUCCESS', payload: res.json() }))
            // If request fails, dispatch failed action
            .catch(() => Observable.of({ type: 'LOGIN_FAILED' }));
          );
    

    【讨论】:

      【解决方案2】:

      问题在于do 允许动作流经您的效果,然后动作再次由商店分派。您可以使用filter 来防止这种情况发生:

      @Effect() selectOfficeFail$ = this.actions$
        .ofType(SelectOfficeActions.LOAD_FAIL)
        .do(() => {
          alert('Error! No offices found!'); // I keep entering here
        })
        .filter(() => false); 
      

      【讨论】:

        【解决方案3】:

        [更新] 现在最好的方法是像这样使用dispatch 选项:

        @Effect({dispatch: false}) selectOfficeFail$ = this.actions$
            .ofType(SelectOfficeActions.LOAD_FAIL)
            .do(() => {
                alert('Error! No offices found!'); // I keep entering here
            });
        

        意思是“对这个动作做出反应,但不发送另一个”。

        【讨论】:

        • 最好的解决方案。
        • 使用 Angular 和 Store >= 7,我需要做 ... this.actions$.pipe(ofType(SelectOfficeActions.LOAD_FAIL), tap(()=>{ alert('no offices'); });
        【解决方案4】:

        如果使用createEffect 函数,则需要将dispatch: false 标志作为配置参数传递(ngrx.io reference

        effectName$ = createEffect(
          () => this.actions$.pipe(
            ofType(FeatureActions.actionOne),
            tap(() => console.log('Action One Dispatched'))
          ),
          { dispatch: false }
          // FeatureActions.actionOne is not dispatched
        );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-13
          • 1970-01-01
          • 1970-01-01
          • 2013-03-17
          • 2021-02-15
          相关资源
          最近更新 更多