0

I have BaseComponent class in my Angular app, which implements destroy$: Subject<void> for observables. Every time I subscribe to service, I'm doing:

this.myService.loadData()
    .pipe(takeUntil(this.destroy$))
    .subscribe(data => this.userData = data);

I want to avoid writing .pipe(takeUntil(this.destroy$)) everywhere and I'm wondering, is there any way to create extension method for observable and handle takeUntil there? for example to move .pipe(takeUntil(this.destroy$)) to my custom method ifAlive and make it look like this:

this.myService.loadData()
    .isAlive()
    .subscribe(...);

Any ideas?

Arkadi
  • 1,153
  • 1
  • 14
  • 35
  • There are other ways. Refer this answer: https://stackoverflow.com/a/60223749/6513921 – ruth Oct 25 '20 at 19:20
  • This answer (https://stackoverflow.com/a/41177163/9423231) covers some options like [until-destroy](https://github.com/ngneat/until-destroy). – frido Oct 25 '20 at 20:24

2 Answers2

1

I believe what you are looking for is an async pipe. Basically you allow angular to do the subscription and unsubscription for you

You simply assign the resulting observable to a variable

In your ts file

data$ = this.myService.loadData()
 

and in your html simply wrap your content with *ngIf='data$ | async as data'

<ng-container *ngIf='data$ | async as data'>

</ng-container>

With the above, Angular will handle the subscription and your code is both easy to read, test and debug

Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74
  • The subtle yet important difference being that if you use this multiple times, you'll end up making your network requests multiple times, and thus a proper replacement would be to multicast this observable. – Ingo Bürk Oct 25 '20 at 21:35
  • 1
    Good point, the `shareReplay` operator will solve this. – jburtondev Oct 26 '20 at 01:17
0

Yes. You could certainly abstract this as you said.

However, the following already unsubscribe for us:

  • async pipe
  • http client requests if it's solely a network request and not a new subscription as a callback

Additionally, from an angular perspective, it's best to unsubscribe on ngOnDestroy, as this is when the component lifecycle ends. Not to say you weren't planning on this, but it could make your abstraction a lot of more complex. Something to consider.

For example, you would still have to store your subscriptions (when in a component, as services won't use ngOnDestroy) and then unsubscribe using your abstraction, which defeats the purpose of the abstraction, because you still have to add some boilerplate code.

So in short, the abstraction is a good idea for services, but for components, it's a lot more complex and I would try to use the async pipe and local unsubscribing as a preferred approach.

jburtondev
  • 2,827
  • 1
  • 14
  • 20