Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 and RXJS, unsubscribe after data received once

Tags:

angular

rxjs

I have a subscribe call that needs to only receive data once. The Angular 2 page that its on is long running.

I want to ensure that the subscription doesn't cause any problems regarding memory leaks and unsubscribes once data is received the first time.

This is my service that makes an api query. It uses .first so it should cleanup once data is received once.

getData(): Observable<string> {
    let _url = SOME_API_URL;
    return this._http.get(_url).first().map((response: Response) => { return response.json(); });
}

This is my Ng2 subscription. Do I need to do anything in this is ensure that everything is cleaned up after the first() data is received?

this._service.getData().subscribe((data: any) => {
    // Do something once.
    // DO I HAVE TO UNSUBSCRIBE OR WILL THE CLEANUP HAPPEN DUE TO THE ABOVE FIRST() CALL?
});

I could use ngDestory but that wouldn't be called as the page is long running and is not often refreshed.

like image 280
Ben Cameron Avatar asked Nov 28 '16 15:11

Ben Cameron


People also ask

Do I need to unsubscribe from a completed observable?

A fundamental aspect of observables is that when they complete, any subscriptions are automatically unsubscribed. As such, if you know an observable will complete then you do not need to worry about cleaning up any subscriptions.

What happens if you don't unsubscribe from an observable?

🎩 Automagically Unsubscribe in Angular 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. A memory leak occurs when a section of memory that is no longer being…

Do I need unsubscribe if Take 1?

These are called “finite subscriptions”. If you subscribe with a “take(1)”, as another example, it is finite and doesn't need to be unsubscribed. This is easy enough to test out if you are unsure of it being finite or infinite. For example, you could console.


1 Answers

first won't subscribe to the Observable for you.

For example, if you do this :

Rx
  .Observable
  .of(1, 2, 3)
  .first()
  .map(x => console.log(x))
<script src="https://npmcdn.com/[email protected]/bundles/Rx.umd.js"></script>

Nothing happen.

So, you need to subscribe to that Observable ... And who says subscribe says that you need to unsubscribe from it yourself.

let subscription = Rx
  .Observable
  .of(1, 2, 3)
  .first()
  .map(x => console.log(x))
  .subscribe(
    (success) => {},
    (error) => {},
    (done) => { console.log('unsubscribe') }
  );

subscription.unsubscribe();
<script src="https://npmcdn.com/[email protected]/bundles/Rx.umd.js"></script>

Just save the subscription in one of your class variable and implements onDestroy method :

ngOnDestroy() {
  this.subscription.unsubscribe();
}

Edit 1 :

Just to be more clear :

If you go through first(), it'll be unsubscribed as you expect.

BUT, let say your observable is taking a very long time and you decide to move somewhere else in your app, and the component gets destroyed. The observable will remain alive (at least until it receives one value).

So you should still keep the ngOnDestroy method in case your component is destroyed before the observable is unsubscribed.

like image 200
maxime1992 Avatar answered Oct 19 '22 05:10

maxime1992