Contents hide 1) The .subscribe() 1.1) Its a lapse of memory 2) The .unsubscribe() 3) Declarative with takeUntil 3.1) Disadvantages Of :takeUntil 4) Using take(1) In this tutorial, we will learn the Best Way To Subscribe And Unsubscribe In Angular 8 application. We will see all the various possible solutions to subscribing to RxJs Observable. Topics The .subscribe() The .unsubscribe() Declarative with takeUntil Using take(1) The .subscribe() Lets first begin with the simple example. we have an dummy API which is a cold observable. Cold Observable is an Observable which will don’t do anything by itself. it has to subscribe to it to start its execution. We will subscribe to the http.get('API-URL') in ngOnInit method of a component and will store the response data in component variable. app.component.ts import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent implements OnInit { API: string = 'https://jsonplaceholder.typicode.com/todos/1'; data: any; constructor(private http: HttpClient){} ngOnInit() { this.http.get(this.API).subscribe( res => { this.data = res; }, err =>{ alert(err); } ); } } Its a lapse of memory The method looks perfect and works exactly as we are expecting, but what if we navigate to some other module or component? The component will get destroyed properly, but the subscription will not destroy. If we console.log(res), the logs will keep getting added into the browser console. And, if we navigated back to the original component i.e. Route. The component would get recreated together with a new subscription. It’s ok to subscribe When some components, for example, AppComponent and most of the services (with exception of services from lazy loaded modules and services provided in @Component decorator) in our Angular application will be instantiated only once during the application startup. Anyhow, these subscriptions will get cleared when we navigate away from application to some other application (Website). other than that we can unsubscribe… see in next point. The .unsubscribe() As we have figured out that we have been implementing the unnecessary lapse of memory,so we can easily get rid of it. Lapse of memory are created when we destroy and recreate the components but we never clean up existing subscriptions. As we go on recreating the components, we always keep adding multiple subscriptions. Subscribing to an observable yields us Subscription object which has an .unsubscribe() method. This method is used to remove the subscription when we don’t need it. let us consider we only having one API in perticular component so we can unsubscribe buy its refrence variable, As example mention below. catalog-results.component.ts import { Component, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Subscription } from 'rxjs'; @Component({ selector: 'sl-catalog-results', templateUrl: './catalog-results.component.html', styleUrls: ['./catalog-results.component.scss'] }) export class CatalogResultsComponent implements OnInit, OnDestroy { data: any; private subscription: Subscription; API: string = 'https://jsonplaceholder.typicode.com/todos/1'; constructor(private http: HttpClient){} ngOnInit() { this.subscription = this.http.get(this.API).subscribe( res => { this.data = res; }, err =>{ alert(err); } ); } ngOnDestroy(){ this.subscription.unsubscribe(); } } AND We might be having the multiple API’s in the single-component we can use as an array of subscriptions so onDestroy we can destroy all the subscriptions. Example: catalog-results.component.ts import { Component, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Subscription } from 'rxjs'; @Component({ selector: 'sl-catalog-results', templateUrl: './catalog-results.component.html', styleUrls: ['./catalog-results.component.scss'] }) export class CatalogResultsComponent implements OnInit, OnDestroy { data1: any; data2: any; private subscriptions: Subscription[] = []; API: string = 'https://jsonplaceholder.typicode.com/todos/'; constructor(private http: HttpClient){} ngOnInit() { this.subscriptions.push(this.http.get(`${this.API}/1`).subscribe( res => { this.data1 = res; }, err =>{ alert(err); } )); this.subscriptions.push(this.http.get(`${this.API}/2`).subscribe( res => { this.data2 = res; }, err =>{ alert(err); } )); } ngOnDestroy(){ this.subscriptions.forEach(subscription => subscription.unsubscribe()); } } Declarative with takeUntil Now let’s dive more into it and make our angular application better with the help of takeUntil RxJS operator. Documentation: takeUntil(notifier: Observable<any>) – Emits the values emitted by the source Observable until a notifier Observable emits a value some.component.ts @component({ /* ... */ }) export class SomeComponent implements OnInit, OnDestroy{ private unsubscribe$ = new Subject<void>; routerActivationEndEvent$: Observable<ActivationEnd>; /* ... */ ngOnInit(){ this.routerActivationEndEvent$ .pipe(takeUntil(unsubscribe$)) .subscribe(res => this.titleService.updateTitle()); } ngOnDestroy(){ this.unsubscribe$.next(); this.unsubscribe$.complete(); } } The above solution is declarative! it means that we declare our Observable before it hand it every thing that it needs to codinate for the whole life cycle from beginning to end. Disadvantages Of :takeUntil Most clearly, it’s quite verbose! we’ve to form extra Subject and properly implement OnDestroy interface in each part of our application that is kind of a lot! The even bigger downside is that it is a quite erring method. it is very simple to forget to implement OnDestroy interface. And this itself will fail in two totally different ways… Forgetting to implement the OnDestroy interface. Forgetting to call .next() and .complete() methods in the ngOnDestroy implementation (leaving it empty) The largest downside with this can be that these 2 things won’t lead to any obvious errors some so that they square measure terribly straightforward to miss! A possible solution would be to implement (or notice if it exists) a custom tslint rule which is able to check for missing (or empty) ngOnDestroy() ways in each element which may even be problematic as a result of not each element uses subscriptions… Using take(1) Some of our API needs to be called once at the start of the application. There might be some process that needs to be load while initializing the application. in such case we can use the RxJS take(1) operator. It is awesome because it directly(automatically) unsubscribe the subscriptions after the first execution of the subscriber. some.component.ts @component({ /* ... */ }) export class SomeComponent implements OnInit{ /* ... */ ngOnInit(){ this.http.get(this.API).pipe(take(1)).subscribe( res => { this.data = res; }, err =>{ alert(err); } ); } The operator itself is take(n: range) thus we tend to might pass any number, except for our situation, the range 1 is all that we need! Get Some More Articles On Angular 7+ Share this:TwitterFacebookRedditLinkedInWhatsAppPrintTumblr Related Tags: Angular 7, RxJS, subscribe, unsubscribe