4

Just curious whether Subscription instances that are not referenced need to be unsubscribed? For example this demo calls:

onSubmit(creds: Creds) {
   this.authService.login(creds).subscribe();
}

So each time the someone logs in a Subscription instance is created and returned, but there are no handles to it.

IIUC these will just be garbage collected, but figure I'd double check just to be on the safe side.

Ole
  • 41,793
  • 59
  • 191
  • 359
  • 2
    yes these need to be captured and unsubscribed inside OnDestroy() method – VithuBati Dec 19 '18 at 02:51
  • So if we don't it creates a memory leak? – Ole Dec 19 '18 at 02:51
  • 1
    yes, of course, it does – VithuBati Dec 19 '18 at 02:53
  • That's what I figured. I assume that the `Subscription` instances hold onto a reference to the source observable so they will stay in memory until the source `Observable` instance is either destroyed or `unsubscribe()` is called on it, disconnecting all observers, and presumably the corresponding subscription objects? – Ole Dec 19 '18 at 02:54
  • Please refer [here](https://stackoverflow.com/a/51850733/2340159) and [here](https://stackoverflow.com/a/41177163/2340159) for more. – VithuBati Dec 19 '18 at 02:58
  • 1
    You don't have to unsubscribe to an observable that will complete, but you need to be careful that it completes during the life-cycle of the object that references it. For components, this is before the OnDestroy is called. – Reactgular Dec 19 '18 at 02:59
  • @cgTag In my particular use case I'll be using a `BehaviorSubject`. So If I call complete() on the `BehaviorSubject` when the application shuts down, then all memory is cleaned up correct? – Ole Dec 19 '18 at 03:08
  • 1
    Observables do not have to complete. Completing an observable does not prevent memory leaks, but subscribing forever to an observable that never completes creates a memory leak. So it is the subscriber who has to worry about it and not the emitter (i.e. an injectable service). – Reactgular Dec 19 '18 at 03:12
  • You can use DisposeBag to facilitate open subscriptions and disposal: https://stackoverflow.com/a/72055787/1100921 – Hamidreza Vakilian Apr 29 '22 at 15:00

1 Answers1

7

If the Observable completes then there is no need to unsubscribe. Observables created with the http service will complete after calling.

That said it is still best to unsubscribe or have a takeUntil clause.

finalise = new Subject<void>();

onSubmit(creds: Creds) {
  this.authService.login(creds).pipe(takeUntil(finalise)).subscribe();
}

ngOnDestroy() {
  this.finalise.next();
  this.finalise.complete();
}

This way you can use the same subject to complete all your Observables instead of managing many subscriptions.

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • 1
    This has the benefits that it will "cancel" a HTTP request if the component is destroyed before it is finished. – Reactgular Dec 19 '18 at 03:11
  • @cgTag Good Tip! – Ole Dec 19 '18 at 03:12
  • You don't have to define the subject as boolean. You can just make it *void*. `finalize = new Subject();` and then `this.finalize.next()`. This will basically emit an *undefined* value. – Reactgular Dec 19 '18 at 03:15
  • So just so I have this branded into my RxJS skills, calling `pipe(takeUntil(finalize)` unsubscribes all the observers when the component is destroyed and also cancels any http requests that may have been started by the source `Observable`? – Ole Dec 19 '18 at 03:22
  • It completes the Observable when finalize emits a value. Just make sure your component implements OnDestroy and you emit a value into finalize in the ngOnDestroy. – Adrian Brand Dec 19 '18 at 03:24
  • 2
    Also make sure that the takeUntil clause is the last function in your pipe, putting any other functions like map and filter before. – Adrian Brand Dec 19 '18 at 03:26
  • Hmmm - Another question - If I create the source `Observable` with a `BehaviorSubject` and have other components that are also listening to the `BehaviorSubject`, will those be disconnected as well when any of the components being multicast to by the `BehaviorSubject` are destroyed? – Ole Dec 19 '18 at 03:32
  • 1
    It will work for any subscriptions no matter what type of Observable. – Adrian Brand Dec 19 '18 at 03:34
  • NPM installable operator that encapsulates the logic in the answer. – Ole Dec 19 '18 at 04:32