0
votes

I started working with a legacy angular 6 application that is using Rxjs observables. The observables within the components don't seem to be using an unsubscribe from what I can see. Example subscribe within the ngOnInit:

this.service.getCustomerDetail(customers).subscribe(
          (data) => {
            this.customerData = data;
          },
          () => {
            this.notify.addNotification(
              new notification(
                `Error retrieving customer data`
              )
            );
          }
        );

The subscribes are using the completion even if nothing in it aka Next, Error, Complete values of Rxjs subscribes but this to me looks like it needs to push these into subscriptions and then on the ngOnDestroy unsubscribe to all of them. Is that correct that these subscriptions without that unsubscribe even if the complete is within the observable would stay in the heap memory aka cause memory leaks?

Using the TakeUntil approach would I use the TakeUntil in the cases where my subscribe is using the error and complete sections for example:

this.service.getCustomerDetail(customers)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
          (data) => {
            this.customerData = data;
          },
          () => {
            //error section
            this.notify.addNotification(
              new notification(
                `Error retrieving customer data`
              )
            );
          },
          () => {
            //complete section
            this.loadAddlDetail();
          }
        );

Thanks for any info on this.

2
The takeUntil method is the preferred angular solution stackoverflow.com/questions/38008334/…Adrian Brand
@AdrianBrand added a question to the description with example would I use takeUntil if I already have a error and complete section to the subscribe?beantownace

2 Answers

2
votes

There are 2 ways to do this. If this is an isolated case the following will suffice

Method 1 - If this is an isolated case

---------------------------------------------------

In class

Change the class Declaration to include the OnDestroy

export class AppComponent implements OnInit, OnDestroy

Add private variable to store the subscription

private serviceSubscription  = null

In ngOnInit

this.serviceSubscription = this.service.getCustomerDetail(customers).subscribe(
      (data) => {
        this.customerData = data;
      },
      () => {
        this.notify.addNotification(
          new notification(
            `Error retrieving customer data`
          )
        );
      }
    );

Implement OnDestroy

ngOnDestroy() {
   if (this.serviceSubscription != null) {
     this.serviceSubscription.unsubscribe()
   }
} 

----------------------------------------------------------

Method 2 - If this seen in multiple places

----------------------------------------------------------

Create a Base Class for Components component-base.ts

import { Subscription } from 'rxjs';
import { OnDestroy } from '@angular/core';

export class ComponentBase implements OnDestroy {
    private subscriptions: Subscription[] = [];

    protected rxs(s: Subscription): void {
        this.subscriptions.push(s);
    }

    ngOnDestroy() {
        this.subscriptions.forEach(x => x.unsubscribe());
    }
}

Extend the component from the ComponentBase

export class AppComponent extends ComponentBase implements OnInit

In ngOnInit

ngOnInit() {
    this.rxs(this.service.getCustomerDetail(customers).subscribe(
        (data) => {
        this.customerData = data;
        },
        () => {
        this.notify.addNotification(
            new notification(
            `Error retrieving customer data`
            )
        );
        }
    ));
}
0
votes

you can use ngOnDestroy() and add the unsubscribe() in it like below

ngOnDestroy() {
 if(serviceSubscription != null){
  serviceSubscription.unsubscribe();
 } 
}

or you can use async pipe on the html template itself, so that you don't have to unsubscribe it manually like below.

<p>{{ observable | async }}</p>