2

The code below creates Observable that passes current Date every second. From the code below I see that Observable<Date> is returned from the ObservableService & subscribed right away in AppComponent. Although Observable<Date> was not saved in AppComponent as a class internal variable, the app continues to receive notifications and the returned Observable<Date> is not collected by the GC.

My question is why it is so, why Observable<Date> was not collected/removed when no object is referencing or capturing it? My main assumption here is that closure in AppComponent : data => this.currentTime = data captures this (AppComponent) but not vise versa. So as Observable<Date> is not captured in AppComponent, Observable<Date> should be removed soon after creation. However it does not happen. Again, what is the reason for this?

observable.service.ts

import { Observable, interval } from 'rxjs';

export class ObservableService {

  createObservableService(): Observable<Date> {
    return new Observable(
      observer => {
        interval(1000)
          .subscribe((_) => observer.next(new Date()));
      }
    );
  }
}

app.component.ts

import { Component } from "@angular/core";
import { ObservableService } from "./observable.service";

@Component({
  selector: 'app-root',
  providers: [ ObservableService ],
  template: `<h1>Custom observable service</h1>
       Current time: {{currentTime | date: 'mediumTime'}}
  `})
export class AppComponent {

  currentTime: Date;

  constructor(private observableService: ObservableService) {
    this.observableService.createObservableService()
      .subscribe( data => this.currentTime = data );
  }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ObservableService } from "./observable.service";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [ObservableService],
  bootstrap: [AppComponent]
})
export class AppModule { }
Ievgen
  • 1,999
  • 2
  • 12
  • 24
  • 2
    Because the observable is indirectly referenced by the browser scheduler (window.setInterval(), window.setTimeout()) used to schedule the action. – JB Nizet Dec 01 '19 at 07:24
  • https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription – martin Dec 01 '19 at 15:32

1 Answers1

-1

Only subscribe to an observable which completes. You can add a complete operator manually (we call that unsubscribe). However it is commonly more recommended to avoid subscriptions and use the async pipe instead. Example for async pipe:

import { Component } from "@angular/core";
import { ObservableService } from "./observable.service";

@Component({
  selector: 'app-root',
  providers: [ ObservableService ],
  template: `<h1>Custom observable service</h1>
       Current time: {{currentTime$ | async | date: 'mediumTime'}}
  `})
export class AppComponent {

  currentTime$: Observable<Date>;

  constructor(private observableService: ObservableService) {
    this.currentTime$ = this.observableService.createObservableService();
  }
}
MoxxiManagarm
  • 8,735
  • 3
  • 14
  • 43