Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: Unsubscribe from http observable in Service

What is the best practice to unsubscribe within a Angular2 service from a http subscription?

Currently I do this but I'm not sure if this will be the best way.

import { Injectable } from "@angular/core";
import { Http } from "@angular/http";

import { Subject } from "rxjs/Subject";
import { ISubscription } from "rxjs/Subscription";

@Injectable()
export class SearchService {
    private _searchSource = new Subject<any>();

    public search$ = this._searchSource.asObservable();

    constructor(private _http: Http) {}

    public search(value: string) {
        let sub: ISubscription = this._http.get("/api/search?value=" + value)
            .map(response => <any>response.json())
            .do(data => this._searchSource.next(data))
            .finally(() => sub.unsubscribe()).subscribe();
    }

}
like image 280
NCC-2909-M Avatar asked Nov 29 '16 08:11

NCC-2909-M


People also ask

Do we need to unsubscribe http observable?

There is no need to unsubscribe from HttpClient observables as they are finite observables, i.e. they complete after emitting a value.

What happens if observable is not unsubscribed?

As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak.

How do I unsubscribe from RxJS observable?

Unsubscribing Manually One method we can use, is to unsubscribe manually from active subscriptions when we no longer require them. RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .


2 Answers

A Service in Angular is a singleton. This means that the service will exist for the entire lifespan of your application.

The reason that you need to unsubscribe from an observable, is to avoid memory leaks. When do you get memory leaks? If something has been garbage collected while it was still subscribed to an observable, event listener, socket, ...

Since an Angular service never get's destroyed, unless your entire application get's destroyed, there is no real reason to unsubscribe from it. The observable will either complete or error or keep going as long as your application does.

Conclusion: Unsubscribing in a service is kind of pointless, since there is no chance of memory leaks.

like image 176
KwintenP Avatar answered Oct 26 '22 20:10

KwintenP


I disagree with KwintenP answer. Yes in case of observable to HttpClient call there is no need to unsubscribe as Vladimir mentioned correctly however in other observables you may definitely need to unsubscribe in a service.

Let see simple example: Assume we have a store that send observables and in the store we have a clicker observable that fire true whenever there is a click on the right mouse (for some weird reason) And assume we have MyWeirdService that do the following:

class MyWeirdService {
  doSomethingUnthinkableManyTimes() {
    this.store.select('clicker').subscribe(() => {
      console.log("Hey what do you know, I'm leaking");
    });
  }
}

this.store.select('clicker') returns an observable that we registering a new handler to it on every call to doSomethingUnthinkableManyTimes without cleaning it resulting in memory leak that will stay as long as the service is there (application lifetime in many cases)

Bottom line you don't need to unsubscribe in the case above of Http as Vladimir explained it well but in other cases you may need it.

-------------- Edition ------------

To solve that issue in my example, just add take(1) and it will unsubscribe automatically after each stream is fired:

class MyWeirdService {
  doSomethingUnthinkableManyTimes() {
    this.store.select('clicker')
     .pipe(take(1))
     .subscribe(() => {
      console.log("What a relief, I'm not leaking anymore");
     });
  }
}
like image 37
Kfir Erez Avatar answered Oct 26 '22 18:10

Kfir Erez