DEV Community

loading...
Cover image for Managing rxjs subscriptions with takeUntil()

Managing rxjs subscriptions with takeUntil()

Nick Raphael
Brought to you by Nick Raphael. Fullstack azure architect and tech lead. Currently neck deep in react - dotnet core - azure stack.
Updated on ・1 min read

Whenever posible we should resist the temptation to subscibe to our observables. If we want to acccess the observable values in our template, it is better to use the async pipe. The async pipe will handle the subscription lifecycle for us. We simple don't have to worry about unsubscribing.

But in those situations where we must subscribe to an observable in our component, we need to handle the unsubscribe ourselves.

The traditional way of unsubscribing is the keep a reference to the subcription and call unsubscibe in ngOnDestroy...

export class MyComponent implements OnInit, OnDestroy {

  private numbersSubscription: ISubscription;
  private lettersSubscription: ISubscription;

  ngOnInit() {
    this.numbersSubscription= of([1, 2, 3]).subscribe(numbers => {});
  }

  someMethodCalledLater() {
    this.lettersSubscription= of(['a', 'b', 'c']).subscribe(letters => {});
  }

  ngOnDestroy() {
    this.numbersSubscription.unsubscribe();
    if(this.lettersSubscription) {
      this.lettersSubscription.unsubscribe();
    }
  }
}

I've used this pattern many times but found that it gets unwieldy when you have a number of subscriptions. A better pattern is to use the takeUntil operator. Lets refactor the same situation...

export class MyComponent implements OnInit, OnDestroy {

  private onDestroy = new Subject();

  ngOnInit() {
    this.numbersSubscription= of([1, 2, 3])
      .takeUntil(this.onDestroy)
      .subscribe(numbers => {});
  }

  someMethodCalledLater() {
    this.lettersSubscription= of(['a', 'b', 'c'])
      .takeUntil(this.onDestroy)
      .subscribe(letters => {});
  }

  ngOnDestroy() {
    this.onDestroy.next();
    this.onDestroy.unsubscribe();
  }
}

This looks simpler to my eyes. We can add any number of subscriptions and all we need to do is add .takeUntil(this.onDestroy) to each call.

Discussion (0)