调度动作后如何防止NgRx效应?

时间:2019-09-16 09:49:02

标签: angular ngrx ngrx-store

我在Angular应用程序中遇到一个非常奇怪的错误。我有一个“注销”按钮,当按下该按钮时,调度一些操作以设置存储中的参数,而这些参数不再需要取消定义。我还有一个名为 Storage 的组件,该组件(除其他外)在其NgOnInit()方法中捕获状态。该方法的结构如下:

    this.store.pipe(select(userProfile)).pipe(
      switchMap( user => {
          if (!currentUser) {
            throw new Error('User must be logged in');
          }
         // ... do something ...
          return this.store.pipe(select(userResources));
        }
      ),
      switchMap(
        response => {
          // ... more operations ...
          return ...
        }
      )
    ).subscribe(
      response => {
        console.log("GOT RESPONSE");
      },
      (error: HttpErrorResponse) => {
        console.log(error);
        console.log("GOT ERROR");
      }
    );

每次显示此组件并调用此方法时,一切都将正常运行,检索所需的状态并将信息显示给用户。奇怪的是,无论何时我经过此组件(例如,我转到“存储”页面然后再返回到主页),如果在按“注销”按钮后,都将引发错误“用户必须登录”。即使我不在显示该组件的页面上,store.pipe也会再次执行! ngOnInit()本身不会被重新执行或调用(当我按Logout时,我毕竟不在该组件中,我只是路过),但是那部分代码被执行了,我也不知道为什么。

此外,我提到的那部分代码似乎执行了我通过“存储”页面传递的次数(例如,如果我通过“存储”页面传递了3次,则在收到3次之后出现“ GOT ERROR”消息)

“注销”按钮执行以下操作:

    this.authenticationService.logout();
    this.router.navigateByUrl(`/`);
    this.resourceStore.dispatch(new Logout());
    this.store.dispatch(new Logout());

有什么主意吗?这里有我不知道的某种连锁反应吗?

1 个答案:

答案 0 :(得分:1)

订阅存在于组件的生存期之外。常见的内存泄漏是在通过ngOnDestroy生命周期挂钩销毁组件时忘记取消订阅。

选择器也将在相关状态改变时触发,从而重复执行

可以找到更全面的讨论here

您可以通过添加以下内容来修复代码:

takeUntil方法

  private destroyed$ = new Subject<void>()

  ngOnDestroy() {
    this.destroyed$.next()
    this.destroyed$.complete()
  }
    this.store.pipe(select(userProfile)).pipe(
      takeUntil(this.destroyed$),
    ... rest of RxJS stream and subscription
    );