调度动作后如何防止 NgRx 影响?

How to prevent NgRx effects after dispatching an action?

我的 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");
      }
    );

每次我显示这个组件并调用这个方法时,一切都很完美,我检索我需要的状态片段并将信息显示给用户。奇怪的是,每当我经过这个组件时(例如,我转到存储页面然后返回主页),如果我之后按下注销按钮,就会抛出错误 "User must be logged in" 作为 store.pipe 会再次执行,即使我不在显示该组件的页面中! ngOnInit() 本身不会重新执行或重新调用(毕竟当我按注销时我不在那个组件中,我只是路过)但是那部分代码被执行了,我不知道为什么。

此外,我提到的那部分代码似乎是按照我通过存储页面的次数执行的(例如,如果我通过存储页面三次,我会收到 "GOT ERROR" 消息三次之后)。

注销按钮会执行类似的操作:

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

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

订阅已超出组件的生命周期。一个常见的内存泄漏是在通过 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
    );