Home Angular Tutorials 3 ways to unsubscribe and avoid memory leak in Angular

3 ways to unsubscribe and avoid memory leak in Angular

by aouidane.med.amine
39,924 views

In this Tutorial we will see the multiples concepts that used to avoid memory leak in angular.

As we know, the performance and the speed of loading of the application is essential to the success of our angular project, fortunately, the Angular team has worked hard to deliver us a framework that providing many tools that enable us to speed up our application and control as much as possible the memory leak of our angular application.  

3 ways to unsubscribe and avoid memory leak

1- Unsubscribe using Aync Pipe

The async pipe is used directly in the template ($observable | async) , it will subscribe to the observable or the promise used by the pipe and returns the last value in the pipeline it has emitted. 

When a new value is emitted, the async pipe request the angular change detector to mark the component as dirty and need to be checked for changes.

The best part and the advantage of using the async pipe is that when the component get destroyed the pipe unsubscribe the observable and we avoid the memory leak automatically.

Let’s see all that in Action! 

In our example, we will create an observable from a simple array, then we will use it directly in our temple using async pipe. 

Note that we could get the observable from a web service that consume an external Api.

				
					
@Component({
  selector: 'app-root',
  template: `<ul>
  <li *ngFor="let user of users;">
    {{ user.id }} : {{ user.name }}  has role   {{ user.role }}
  </li>
</ul>`
})
export class AppComponent implements OnInit {
  users$: Observable<User[]>;

const userList$: Observable<User[]> = of([
  { id: "1x54srt", name: "XperTuto", role: 'admin' },
  { id: "985erf8", name: "Aouidane", price: 'guest' },
  { id: "s8f85ty", name: "amine", price: 'guest' },
]);
  constructor() {}


 // we can get the data from API too
  getUserList():Observable<User[]> {
  
  return of([
  { id: "1x54srt", name: "XperTuto", role: 'admin' },
  { id: "985erf8", name: "Aouidane", price: 'guest' },
  { id: "s8f85ty", name: "amine", price: 'guest' },
]);
  }

  ngOnInit() {
    this.users$ = this.getUserList();
  }
}

				
			

2- Unsubscribe using the "unsubscribe" method

In angular, when we subscribe an observable, the stream will stay open and can be used from anywhere in the application for every new emitted value,

the stream will be closed only by calling the unsubscribe method, so that may cause a memory leak problems if w forget to close the data stream of our observable.  

Let’s see that in Action !

In our example, we will use an observable that emit a new value every 5 second,

so when we subscribe to the observable we will get a new value every 5 second, but the stream will stay open, and we will see the log of the data in the browser console even if we destroy the component because we have destroyed the component, but we have not canceled the observable subscription

that will cause a memory leak, that’s why we should unsubscribe our observable to avoid memory leak in our Angular application. 

				
					export class AppComponent implements OnInit,OnDestroy  {
    subscription: Subscription
    ngOnInit () {
        var observable = Rx.Observable.interval(5000);
        this.subscription = observable.subscribe(x => console.log(x));
    }
	
	 ngOnDestroy() {
        this.subscription.unsubscribe()
    }
}

				
			

The best way to call the unsubscribe method is inside the ngOnDestroy() method, that mean, when we destroy the component, we cancel the observable subscription.

3- Unsubscribe using Rxjs Operators

Angular provide us a powerful library that enable us to control the observable stream of data called Rxjs , this library provide us multiple operators and that allow us to take what we need and when we need from our stream of data.

1- Rxjs Operators : Take () & first()

when we use the operator take(1) or the operator first(), that mean, we will subscribe to the observable, get only one emitted value and unsubscribe.

The operator take(x) accept a number as parameter, so we can indicate the number of emitted values that we need to get. 

Note that event if we destroy the component, the stream stay open unless it emit a value.

That’s why I advise using the unsubscribe method to do this job.

				
					
export class AppComponent implements OnInit {
    subscription$ : Subscription;
    ngOnInit () {
        var observable$ = Rx.Observable.interval(5000);
        this.subscription$ = observable$.pipe(take(1)).
        subscribe(x => console.log(x))
     }
}

				
			

2- Rxjs Operator : takeUntil(subject)

when we subscribe to an observable, we can keep the stream open until a condition that we put in the pipe.

This condition generally is a simple subject that emit a value, so our observable subscribe and keep listening to this Subject, as soon as the subject emit a new value, the observable close the stream, and unsubscribed automatically.

the best place to emit the subject value is in the ngOnDestroy method, the moment when the component destroyed.

				
					export class AppComponent implements OnInit, OnDestroy {
    unsubscribe = new Subject();
    ngOnInit () {
        var observable$ = Rx.Observable.interval(5000);
        observable$.pipe(takeUntil(this.unsubscribe))
        .subscribe(x => console.log(x));
    }
    ngOnDestroy() {
        this.unsubscribe.next()
        this.unsubscribe.complete()
    }
}

				
			

3 – Rxjs Operator : takeWhile(condition)

this operator is a little similar to the previous operator, they are both used to accept a condition, meanwhile this operator enables us to get the emitted new values and keep the stream open while the condition is satisfied.

We will use the same previous example using the interval data stream.

				
					export class AppComponent implements OnInit, OnDestroy {
    subscription$ : Subscription;
    ngOnInit () {
        var observable$ = Rx.Observable.interval(5000);
        this.subscription$ = observable$.pipe(takeWhile(value => value < 5))
        .subscribe(x => console.log(x));
    }
    ngOnDestroy() {
        this.subscription$.unsubscribe()
    }
}

				
			

in this example,  the observable will stay open and get only the emitted  values < 5 every 5 seconds.

Note that the observable will stay open event if we destroy the component until we emit a value > 1 (if the condition is not satisfied, so Unsubscribe)

if we see the console log, we will see only { 1 , 2 , 3 , 4 }

In this tutorial, we have leaned when and how to use the multiples methods provided by Angular to avoid memory leak in our application thought multiples examples.

I hope you enjoy reading this Tutorial.

You may also like