55

I got asked by one of my colleagues if we need to unsubscribe from the afterClosed() Observable of a Dialog.

We are using the takeUntil pattern to unsubscribe from all Observables on ngOnDestroy().

this.backEvent = fromEvent(window, 'popstate')
    .pipe(
        takeUntil(this.destroy$)
    )
    .subscribe(
        () => {
            this.navigationService.backClicked = true;
            this.navigationService.navigateBackToDirectoryCenter();
        }
    );

ngOnDestroy()

ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
}

So is it necessary to unsubscribe from afterClosed() Observable?

dialogRef.afterClosed().subscribe(
    (data) => {
            console.log(data);
        }
    },
);

or?

dialogRef.afterClosed()
    .pipe(
        takeUntil(this.destroy$)
    )
    .subscribe(
        (data) => {
            console.log(data);
        },
    );
liqSTAR
  • 1,225
  • 1
  • 12
  • 22

4 Answers4

108

No

You don't need to unsubscribe as the observable itself completes.You can verify the same by adding a finalize block to see whether observable completes itself or not.

import { finalize } from "rxjs/operators";
dialogRef
  .afterClosed()
  .pipe(finalize(() => console.log("completed")))
  .subscribe(data => {
    console.log(data);
  });

And when you will close the dialog, you will see completed in console, this depicts that you do not need to unsubscribe the observable.

Community
  • 1
  • 1
Archit Garg
  • 2,908
  • 2
  • 14
  • 22
  • 2
    Does it work the same way if you chain some observables using `switchMap`? – wisnix Jul 18 '20 at 12:42
  • `switchMap` throws away the observable from `afterClose()` and takes over with observable from `switchMap` callback, which needs to complete properly. – mr.vea Aug 18 '22 at 20:23
9

You usually want to unsubscribe from observables to prevent memory leaks and to prevent errors, when the subscribe block uses this.xxxx component property.

Even though the subscription completes and you do not need to think about a memory leak, you should be aware of the second problem.

The host component that calls dialogRef.afterClosed() might get destroyed while the dialog is still visible. The subscription would emit after close and when you access a component property inside the subscribe block, it would throw an error.

I think it's a rare situation, that the host component get destroyed while a dialog is active, but I wanted point that edge case. An example could be a Floating Button that opens a Dialog but disappears after scroll or other circumstances.

Simon Hansen
  • 622
  • 8
  • 15
5

Good question, just had a look at the docs (https://material.angular.io/components/dialog/overview) , nothing seems to hint towards the need to unsubscribe at all, what you already have should suffice.

  • 1
    I don't think the docs go into that much detail and unsubscribing might simply be outside of the scope of the doc. So I wouldn't rely on "if it's not mentioned in the docs, then it's not needed". – ulmas Apr 07 '22 at 20:25
1

You can test this yourself by setting the complete callback in the subscribe call. I tested this long ago to confirm what others here are saying; no you do not need to worry about unsubscribing. Testing for this is a good-know practice regardless.

observable.subscribe(
    (value) => { ... },
    (error) => { ... },
    () => { console.log('complete!'); }
);
ktamlyn
  • 4,519
  • 2
  • 30
  • 41