RxJs可观察对象重复值

4

我有一个非常简单的场景。一个对象和一个可观察者。当客户端登录成功时,我会发布成功消息,当用户注销时,我会发布失败消息。

问题出现在 LoginComponent 中的 subscribe 方法中。 第一次一切正常。用户登录后我收到一个事件,但是之后,当用户再次注销并重新登录时,我收到两个相同的事件;如果用户注销然后再次登录,我收到三个重复事件,以此类推。

AuthService.ts

public _loggedIn: Subject<LoggedInOrResetPassword> = new Subject();
public loggedId: Observable<LoggedInOrResetPassword> = this._loggedIn.asObservable();


obtainAccessToken(){
 // ommitted
 this.httpClient.post(environment.baseUrl + url, null, requestOptions)
                .subscribe(data => {
                  this.saveToken(data);
                  this._loggedIn.next(LoggedInOrResetPassword.createTrue());
                });
  // ommitted
}


private logout(navigateTo?: string){
    this._loggedIn.next(LoggedInOrResetPassword.createFalse());
}

LoginComponent.ts

ngOnInit() {
    this.authservice.loggedId.subscribe( ( loggedInOrResetPassword: LoggedInOrResetPassword ) => {
    // HERE I GET DUPLICATE VALUES
});
1个回答

2
原因是在LoginComponent被销毁时,您没有取消订阅。
您需要更改代码如下:
首先,在LoginComponent中添加一个实例属性来存储订阅,例如:
export class LoginComponent implements OnInit, OnDestroy {
  .....
  loginSubscription: Subscription;
  .....
}

然后修改ngOnInit,将订阅存储在新添加的属性中。

ngOnInit() {
    this.loginSubscription = this.authservice.loggedId.subscribe( ( loggedInOrResetPassword: LoggedInOrResetPassword ) => {
    // HERE I GET DUPLICATE VALUES
});

最终添加ngOnDestroy以确保在组件被销毁时取消订阅。
ngOnDestroy {
  if (this.loginSubscription) {
    this.loginSubscription.unsubscribe();
  }
}

作为订阅可观察对象(Observable)并自动取消订阅的另一种方法,可以看一下 Angular 的 async 管道。


这个有效,谢谢。这是否意味着我应该总是取消订阅?您能否解释一下这部分内容:“原因是当 LoginComponent 被销毁时,您正在取消订阅。” 我不明白这是为什么,因为在您向我展示如何取消订阅之前,我并没有取消订阅。如果我不取消订阅,为什么会触发重复事件?谢谢。 - SeaBiscuit
1
这里有一个拼写错误。正确的回答应该是“原因是你没有取消订阅”。我已经更正了答案。一般来说,在组件方法中订阅 Observable 时,除非你确定组件的销毁与 App 的关闭相符(例如标准的 AppComponent),否则你应该始终确保在 ngOnDestroy 中取消订阅。 - Picci
1
你可以使用 takeUntil,而不是手动取消订阅,就像这篇文章中所示:https://dev59.com/ZFoT5IYBdhLWcg3w8S-2 - ggradnig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接