1

I am working on an Angular 8 project using @angular/mdc-web as a wrapper for Material Design. Today I had to fix a bug revolving around an error dialog. The dialog presents an error message and can be closed by clicking an OK button. Pretty straight forward and everything worked as a charm until I got an issue defect reported by the QA guys the day after I implemented it. Apparently, some UI elements (buttons) stopped working after the dialog was closed.

In order to examine the bug, I subscribed to the Observable that was returned by the app's central openDialog function, and suddenly the bug didn't occur anymore. Here is the relevant code of the openDialog function:

const dialogRef: MdcDialogRef<T> = this.dialog.open(
  // irrelevant stuff ommitted
);

return dialogRef.afterClosed().pipe(
  tap(
    () =>
      (this.dialogRefArray = this.dialogRefArray.filter(
        item => item.id !== data.id
      ))
  ),
  delay(500),
  tap(() => this.navigationBlocker.unregister(data.id)),
  map(resultFn)
);

Now, I am rather new to Rxjs, and my question is: Why is afterClosed only called when I have subscribed to it? Like this:

const dialog = this.dialogService.openDialog(
  // irrelevant stuff ommitted
).subscribe(() => {
  dialog.unsubscribe();
});

I don't even need to unsubscribe to make it work. I'm trying to understand how Observables work. I would have suspected that afterClosed is being called when ever the dialog is closed, similar to an event. Why do I have to subscribe to it?

An explanation is greatly appreciated, cheers.

Serg Derbst
  • 444
  • 6
  • 18
  • 4
    See [RxJS: Hot And Cold Observables](https://alligator.io/rxjs/hot-cold-observables/). I think that will clear up any confusion. Let me know if you still have questions about it. – Igor Aug 19 '20 at 12:54
  • 1
    See the link from @Igor for differences b/n hot and cold observable. Without the grasp of RxJS observables, it won't be possible to understand the need for `subscribe`. A cold observable is akin to ordering a pizza in a restaurant. The dough (source observable) and the toppings (operators - `tap`, `delay`, `map`,...) are available. But the pizza won't be prepared until you place the order. Subscribing is similar placing the order. The dough is topped with your preferences and the pizza (notification from the observable) is delivered. A cold observable is **roughly** similar to a frozen pizza. – ruth Aug 19 '20 at 13:27
  • Thank you very much for the link. It makes total sense once you read it. :) – Serg Derbst Aug 21 '20 at 06:37

2 Answers2

4

The explanation is really simple. An observable only emit when you subscribe to it.

Also, even if you don't need to unsubscribe to make it works, it's a good pratice to unsubscribe in order to avoid memory leaks (if it still emit, you will still execute the subscribe callback).

Boursomaster
  • 202
  • 1
  • 5
  • 15
1

afterClosed is a function. It's called when you call it. This function returns a hot observable. This observable emits an item when the dialog has finished closing.

The operators tap, delay and map (like most operators) only subscribe to their source when they are subscribed to. By subscribing to the final observable you trigger a chain of subscriptions. You can imagine this as if each operator subscribes to the operator above in the chain.

Subscribing to a hot observable is like listening to a speaker. If you don't listen you won't know what the speaker said and can't act upon it.

frido
  • 13,065
  • 5
  • 42
  • 56