Angular RxJS Observable: takeUntil vs. unsubscribe with a Subscription

Horace P. Greeley picture Horace P. Greeley · Oct 17, 2019 · Viewed 9.9k times · Source

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: ?

Answer

Mark van Straten picture Mark van Straten · Oct 17, 2019
  • 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.