How to use take(1) in Angular 6?

Derrick Miller picture Derrick Miller · Aug 4, 2018 · Viewed 7k times · Source

Can someone please illustrate the syntax for take(1) in Angular 6 / rxjs 6?

In the code below, I retrieve a document from Firestore and then make it available as an observable.

I then subscribe to that observable, read the timestamp of the document, and format the age in human-readable format. That works great, however it does not need to execute every time there are changes in the document stream. It only needs to execute one time, since the document timestamp is never, ever going to change.

How can I modify this code to incorporate take(1), so that the age string is only generated once and the subscription to items is not kept open? I cannot find any clear example of the syntax for take(1) under Angular / rxjs version 6. All of the examples I can find are for previous versions.

import { Component, Input, OnChanges } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Item } from '../../interfaces/item';

@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.scss']
})
export class ItemComponent implements OnChanges {

  @Input() itemId: string;
  private itemDoc: AngularFirestoreDocument<Item>;
  public item: Observable<Item>;
  public age: string;

  constructor(private afs: AngularFirestore) {}

  ngOnChanges() {

    if ( this.itemId ) {

      this.itemDoc = this.afs.doc<Item>('items/' + this.itemId);
      this.item = this.itemDoc.valueChanges();

      this.item.subscribe(thisitem => {
        this.age = Utils.getFormattedAgeString(thisitem.timestamp);
      });

    }

  }

}

Answer

Anton Sorokin picture Anton Sorokin · Aug 4, 2018

You can apply pipe operators to any observalble with a Observable pipe function which takes any number of pipe operators as arguments. For instance in your case you can use pipe right before subscribe call as follows:

  this.item
    .pipe(
      take(1)
      // and any other pipe operators like map if required
    )
    .subscribe(thisitem => {
      this.age = Utils.getFormattedAgeString(thisitem.timestamp);
    });

Pipe operators were introduced to utilize such features as tree shaking in a more efficient way allowing bundle optimizers to only keep the code for pipe functions which are explicitly refernced in a code.

More details can be found in the official docs.