29

I just watched a ngConf video of John Papa talking about SubSink as a best practice in order to unsubscribe from obversables.

I was actually using Subscriptions[] then push subscriptions into it then forEach unsubscribe at cmp destroy.

Is their something I missed or is it just a readability improvment to use SubSink ?

The Segfault
  • 939
  • 1
  • 10
  • 23

2 Answers2

35

Another way, without installing third party libraries is to group subscriptions up with .add() method

export class CustomerComponent implements OnInit, OnDestroy {
  constructor(
    private dataService: DataService
  ){}

  private subs = new Subscription();

  ngOnInit() {
    this.subs.add(this.dataService.getCustomer().subscribe());
    this.subs.add(this.dataService.getProducts().subscribe());
  }

  ngOnDestroy() {
    this.subs.unsubscribe();
  }
}
Shogg
  • 796
  • 2
  • 7
  • 14
  • 5
    This is the answer. No subsink needed, the functionality is already in Subscription. Or was it put aftewards? You can build a base component with a subscription that is unsubscribed on destruction. Then inherit the component in every other component and add subscriptions to that base subscription. You're done. – ginalx Mar 13 '20 at 13:28
  • I really find it difficult to understand while you guys have to make the big deal about using subsink. This approach is a correct but in my opinion, I don't see any benefit over subsink. According to you, one still has to inherit the custom component in every other component where needed and add all subscriptions to the base subscription. Is that not exactly what subsink is doing but cleaner? @Llorenç Pujol Ferriol correctly pointed out that you can always use async and fall back to subsink as needed in any project. – omostan May 30 '20 at 08:21
  • 4
    To use subsing is required to install third party library "npm install subsink". I don't want to install this library, learn it (even if it's a very simple library) if i can get what i want without this subsink library – Shogg Jun 04 '20 at 12:56
17

Adopting this way has at least one benefit - you move this code outside of your application logic. Because unsubscribing is just a clean up (a must). It is not related with the logic you create in your app.

And moving one step further, you can omit ngOnDestroy from components and create one adapter with NgOnDestroy implemented and place all logic there.

import { OnDestroy } from '@angular/core';
import { SubSink } from './sub-sink';

/**
* A class that automatically unsubscribes all observables when 
* the object gets destroyed
*/
export class UnsubscribeOnDestroyAdapter implements OnDestroy {

/**The subscription sink object that stores all subscriptions */
subs = new SubSink();

/**
* The lifecycle hook that unsubscribes all subscriptions 
* when the component / object gets destroyed
*/
ngOnDestroy(): void {
   this.subs.unsubscribe();
}

How to automatically unsubscribe your RxJs observables

Other than that, it is a very tiny package, only few lines of code. Thanks for sharing :)

Julius Dzidzevičius
  • 10,775
  • 11
  • 36
  • 81
  • 1
    IMO having to extend it is what it makes not worth it. Only by extending it, it means that you should always remember to do super.ngOnDestroy in your parent component (if you have ngOnDestroy logic there), that you will forget one day (leak). Also extending it doesn't let you extend any more things by default, unless you have some mixins architecture or whatever. I don't see enough value to adopt it. – Llorenç Pujol Ferriol May 20 '19 at 11:31
  • I worked on a few Angular projects, written not by me, also worked on quite some my own projects and so far I never needed to extend Component or saw one. Maybe for UI components could be useful, but other than that I never faced such situation. And for UI components, we can use `async`. So for me, this is totally fine + it wouldn't be hard to fall back if there was a need to extend Component with something else, because this feature is very unlikely to grow in the feature. – Julius Dzidzevičius May 20 '19 at 12:33
  • About forgetting - unsubscribing also could be forgotten :) And here you can forget only one call, while unsubscribing manually, you could forget all or only few subscriptions. – Julius Dzidzevičius May 20 '19 at 12:33
  • Yeah sure, forgot can always happen:), but if you inherit some logic, is easier. I know that because I work on a huge project where inheritance between components/services/classes actually happens and we faced multiple related problems with that. The fallback is easy, I agree, you will end up doing unsubscription manually without inherit UnsubscribeOnDestroyAdapter, true story in a similar case. The cost and complexity of doing some kind of multiple inheritance is not worth it for as little inherit logic. – Llorenç Pujol Ferriol May 20 '19 at 13:37
  • 1
    SubSink is not bad, but better without inherit. In small project I maybe could see value on it, since it speeds component creation etc. but not in big ones. As you said, the perfect/cleanest solution nowadays is use the async pipe whenever you can. Async pipe for the win lol. – Llorenç Pujol Ferriol May 20 '19 at 13:48
  • I really find it difficult to understand while you guys have to make the big deal about using subsink. This approach is a correct but in my opinion, I don't see any benefit over subsink. Is this here not exactly what subsink is doing but cleaner? @Llorenç Pujol Ferriol correctly pointed out that you can always use async and fall back to subsink as needed in any project. – omostan May 30 '20 at 08:24