0

I'm trying to understand best practice in using ngDestroy or unsubscribe when calling an angular service. With the example below, can someone show me how you would properly use ngDestroy in this situation?

this.submitPostService.getUserName(this.userId).subscribe(user => {
  console.log("THIS IS THE USER!");
  console.log(user);
  this.username = user.posts.name;
  console.log(this.username);
});

angular service

  getUserName(id: string) {
    return this.http.get<{ posts: any }>(
      `http://localhost:3000/api/user/${id}?username=` + id
    );
  }
Andy
  • 185
  • 2
  • 6
  • 22
  • It depends. What is the code of getUserName()? How many times and when does the observable it returns emit? – JB Nizet Dec 18 '19 at 19:12
  • Does this answer your question? [Angular/RxJs When should I unsubscribe from \`Subscription\`](https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription) – thenolin Dec 18 '19 at 19:17
  • 2
    Since you're returning the http client observable there is no need to unsubscribe from it. – nll_ptr Dec 18 '19 at 19:19
  • 1
    ```http``` observables complete, so there's no need to ```unsubscribe``` from them – maury844 Dec 18 '19 at 19:24
  • Oh ok. Then whenever I make an http call from a service, I won't worry about it then. Thanks – Andy Dec 18 '19 at 19:35

3 Answers3

1

Look at the following example. This is the way I make sure the unsubscribe will always occur when destroying the component.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
//...

export class AppComponent implements OnInit, OnDestroy {
  private destroyed$ = new Subject();
  //...

  ngOnInit() {
    this.submitPostService.getUserName(this.userId)
      .pipe(takeUntil(this.destroyed$))
      .subscribe(user => {
        console.log(user);
    });
  }

  ngOnDestroy() {
    this.destroyed$.next();
    this.destroyed$.complete();
  }
}

The key elements here are destroyed$ and takeUntil a rxjs operator. In your service call you can use .pipe(takeUntil(this.destroyed$) that in easy words it is, subscribe until destroyed$ is true. You can use this in all your components subscriptions.

Hope this help (: You can take a look at this article for more.

Gustavo Santamaría
  • 837
  • 1
  • 10
  • 21
0

you must first save the observable in a class-level variable

this.subscription = this.submitListingService.getUserName(this.userId).subscribe(...

then in the component destruction method or another method you can call the method unsuscribe

this.subscription.unsuscribe();
maury844
  • 1,210
  • 15
  • 25
0

For your example, the http.get is a self-completed method, which means you don't need to unsubscribe by component itself. you can have a look on similar issue: Is it necessary to unsubscribe from observables created by Http methods?

I guess following template is enough for view logic only components:

export class AppComponent implements OnInit, OnDestroy {
    renderTimeSubs: Subscription[] = [];
    keepUpdateSub1: Subscription = null;
    constructor(private aService: AService) {}

    ngOnInit() {
      this.renderTimeSubs = [];
      this.aService.selfClosedObs.subscribe();// you don't need to handle the self-completed subscription
      const sub1 = this.aService.nonSelfClosedObs().subscribe();
      this.renderTimeSubs.push(sub1);
    }
    updateSubscription() { /** handle in service is a better manner */
        if (this.keepUpdateSub1 && !this.keepUpdateSub1.closed) {
            this.keepUpdateSub1.unsubscribe();/** close Observable between Init&Destroy component*/
        }
        this.keepUpdateSub1 = aService.getANewNonClosedObservable;/** new non-closed Observable*/
    }
    ngOnDestroy() {
      this.renderTimeSubs .forEach(x => x.unsubscribe());
      if (this.keepUpdateSub1 && !this.keepUpdateSub1.closed) {
        this.keepUpdateSub1.unsubscribe();
      }
    }
}