Search code examples
angularrxjsobservableunsubscribe

Angular RxJS Observable: takeUntil vs. unsubscribe with a Subscription


There are several ways to unsubscribe from observables on Angular components (by using ngOnDestroy). Which option below should be preferred and why (e.g. technical reasons, performance, etc.)?

Option 1: takeUntil

Using RxJS takeUntil to unsubscribe

@Component({
  selector: "app-flights",
  templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
  private readonly destroy$ = new Subject();

  public flights: FlightModel[];

  constructor(private readonly flightService: FlightService) {}

  ngOnInit() {
    this.flightService
      .getAll()
      .pipe(takeUntil(this.destroy$))
      .subscribe(flights => (this.flights = flights));
  }

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

Option 2: .unsubscribe()

Explict call .unsubscribe(), e.g. by using a separate subscription instance

@Component({
  selector: "app-flights",
  templateUrl: "./flights.component.html"
})
export class FlightsComponent implements OnDestroy, OnInit {
  private readonly subscriptions = new Subscription();

  public flights: FlightModel[];

  constructor(private readonly flightService: FlightService) {}

  ngOnInit() {
    const subscription = this.flightService
      .getAll()
      .subscribe(flights => (this.flights = flights));

    this.subscriptions.add(subscription);
  }

  ngOnDestroy() {
    this.subscriptions.unsubscribe();
  }
}

Option 3: takeWhile

Using RxJS takeWhile unsubscribe

Option n: ?


Solution

    • Option 1: clean & explicit. Works like a charm
    • Option 2: more procedural, less stream-like. Works like a charm. Note that your stream will not get a 'complete' event which can cause unexpected behaviour
    • Option 3: takeWhile - will have the subscription stay around untill an emission is created and then the takeWhile is evaluated. This can lead to unexpected behaviour. Still, in the end works

    TLDR; there is no wrong here. Choose what you see fits your needs and communicates your intent.

    Ben Lesh has also written quite a good post about the different ways to unsubscribe https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

    His opinion:

    You should probably be using operators like takeUntil to manage your RxJS subscriptions. As a rule of thumb, if you see two or more subscriptions being managed in a single component, you should wonder if you could be composing those better.