2

I want to process data from an Observable just one single time, but then I still have to unsubscribe to prevent memory leaks as far as I understand.

What is the smartest way to do that?

By using pipe(take(1)) or pipe(first()) I already limited the subscription to one event but I still have an open Subscription which is unnecessary after the first execution or is it then automatically unsubscribed?

private user: Observable<User>;

constructor(private afAuth: AngularFireAuth, private afStore: AngularFirestore) {
   this.user = this.afAuth.authState.pipe(
      switchMap((user: firebase.User) => {
         if (user) {
            return this.afStore.doc<User>(`users/${user.uid}`).valueChanges();
         } else {
            return of(null);
         }
      })
   );
}

private someFunction(): void {
   ...
   this.user.subscribe((user: User) => {    // or this.user.pipe(first()).subscribe
      console.log(user);
   });
   ...
   // maybe unsubscribe here, but what if we unsubscribe before executing code atleast once
}

If I unsubscribe too early there is a potential risk of not getting data once.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Ragyal
  • 45
  • 7
  • Possible duplicate of [Angular 2 using RxJS - take(1) vs first()](https://stackoverflow.com/questions/42345969/angular-2-using-rxjs-take1-vs-first) – user184994 Jul 06 '18 at 18:55
  • There is a pretty nice answer over here: https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription – bodorgergely Jul 06 '18 at 19:03

2 Answers2

2

Thanks to user184994!

Using take(1) or first() the subscription gets automatically unsubscribed afterwards.

I tested it like this:

private sub;

...

private someFunction(): void {
   this.sub = this.user.subscribe((user: User) => {
      console.log(user);
   })

   ...

   if (this.sub.closed) {
      console.log("Subscription unsubscribed :)");
   } else {
      console.log("Subscription still alive :(");
   }
}
Ragyal
  • 45
  • 7
0

What I do is create a subscription

private mySub: Subscription;

then your code

   this.mySub = this.user.subscribe((user: User) => {    // or this.user.pipe(first()).subscribe
  console.log(user);
 });

Then on NgOnDestroy:

this.mySub.unsubscribe();
Taranjit Kang
  • 2,510
  • 3
  • 20
  • 40
  • I don´t want to keep the subscription alive when it isn´t used anymore. So I think a dedicated property for the subscription would be an overkill. – Ragyal Jul 06 '18 at 19:19
  • in that case, just subscribe in the template using async pipe, or just unsubscribe after you subscribe. – Taranjit Kang Jul 06 '18 at 19:20
  • I am not using it in the template and unsubscribing manually could lead to unwanted behaviour since I could unsubscribe too early. – Ragyal Jul 06 '18 at 19:27