4

So i have pretty straight forward scenario. One subject and observable. When client logs in i publish success, when user logs out i publish false.

Problem is in subscribe method in LoginComponent First time everything works great. User logs in i get one event, but after that when user logs out second time and logs in again i get 2 same events, again if user logs out and then logs in i get 3 duplicate events and so on.

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
});
SeaBiscuit
  • 2,553
  • 4
  • 25
  • 40

1 Answers1

2

The reason is that you are NOT unsubscribing when LoginComponent is destroyed.

Your code should be changed as follows

First add an instance property to LoginComponent to store the subscription, such as

export class LoginComponent implements OnInit, OnDestroy {
  .....
  loginSubscription: Subscription;
  .....
}

Then change ngOnInit so that you store the subscription in the newly added property

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

Eventually add ngOnDestroy to make sure you unsubscribe when the component gets destroyed

ngOnDestroy {
  if (this.loginSubscription) {
    this.loginSubscription.unsubscribe();
  }
}

Take a look at the async pipe of Angular as an alternative method to subscribe to Observables and automatically unsubscribe.

Picci
  • 16,775
  • 13
  • 70
  • 113
  • This works thanks. Does this mean i should always unsubscribe? And could you please explain this part "The reason is that you are unsubscribing when LoginComponent is destroyed." I am afraid i did not understand this because i was not unsubscribing before you showed me how to. And why this triggers duplicate events if i dont unsubscribe. Thanks – SeaBiscuit Aug 19 '18 at 15:08
  • 1
    There was a typo. Correct response should have been "the reason is that you are NOT unsubscribing". I correct the answer. Generally speaking, any time you subscribe to an Observable in a Component method, you should always make sure that you have the corresponding `unsubscribe` in `ngOnDestroy`, unless you are sure that the destruction of the Component is coincident with the close of the App (e.g. like with standard AppComponent). – Picci Aug 19 '18 at 16:03
  • 1
    Instead of unsubscribing manually, you can also utilize `takeUntil` as shown in this post: https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription – ggradnig Aug 19 '18 at 16:58