take(1) vs takeUntil-unsubscribe

best-practices typescript rxjs

General Guidelines

First and foremost, try to use the async pipe to subscribe to your observable. It handles unsubscribe automatically.

If you have to use .subscribe() for any reason, then choose between the take(1) option and the takeUntil-unsubscribe option.

Use take(1) when you need to subscribe to only one output of the observable and then immediately unsubscribe. Typically, http requests emit just one value. This is a good use case to use take(1).

Use takeUntil-unsubscribe when you need to listen to all the events emitted by the source observable until the component is destroyed. Typically, mouse events and keyboard events are a good use case for this.

Sample implementation of take(1)

this.myObservable$.pipe(take(1)).subscribe(myValue => {
  // do something
});

Sample implementation of takeUntil

import { Component, OnDestroy, OnInit } from '@angular/core';
// RxJs 6.x+ import paths
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { BookService } from '../books.service';

@Component({
    selector: 'app-books',
    templateUrl: './books.component.html'
})
export class BooksComponent implements OnDestroy, OnInit {
    private ngUnsubscribe = new Subject<bool>(); (1)

    constructor(private booksService: BookService) { }

    ngOnInit() {
        this.booksService.getBooks()
            .pipe(
               startWith([]),
               filter(books => books.length > 0),
               takeUntil(this.ngUnsubscribe) (2)
            )
            .subscribe(books => console.log(books));

        this.booksService.getArchivedBooks()
            .pipe(takeUntil(this.ngUnsubscribe)) (3)
            .subscribe(archivedBooks => console.log(archivedBooks));
    }

    ngOnDestroy() {
        this.ngUnsubscribe.next(true); (4)
        this.ngUnsubscribe.complete(); (5)
    }
}
1 Declare a subject that emits a bool.
2 takeUntil guarantees that the observable will be cleaned up once ngUnsubscibe emits true and completes in the ngDestroy method.
3 takeUntil must be the last operator in the pipe before the call to subscribe.
4 Publish a true value.
5 Complete the subscription.
It’s important to add the takeUntil operator as the last one to prevent leaks with intermediate Observables in the operator chain.

References