DEV Community

Bipon Biswas
Bipon Biswas

Posted on

RxJS Map, Tap and Take in Angular

To pipe each emitted value through a sequence of operators, we call the pipe method. Be sure to insert it before the subscribe.

Now we specify the operators. First let's transform the values.

Which operators do we use to transform the values ? If you said map, you are correct. We'll use map to transform the emitted value, multiplying it by 2.

The observable pipe method take any number of operators separated by commas.

Let's add a second map operator to transform the value again, subtracting 10. We now see the transformed items in the console.

    from ([20, 15, 10, 5]).pipe(
      map(item => item * 2),
      map(item => item -10)
    ).subscribe({
      next: (item) => console.log(`resulting item.. ${item}` ),
      error: (err) => console.log(`error occoured ${err}`),
      complete: () => console.log('Completed')
    })
Enter fullscreen mode Exit fullscreen mode

Omitted items
To log the originally omitted item as well, let's add a tap at the beginning of the sequence.

tap example
Now see our originally omitted item along with resulting transformed item.
Zero detected

Notice the 0 we see here in the result.

    from ([20, 15, 10, 5]).pipe(
      tap(item => console.log(`emitted item ... ${item}`)),
      map(item => item * 2),
      map(item => item -10),
      map(item => {
        if(item === 0){
          throw new Error ('Zero detected');
        }
        return item;
      })
    ).subscribe({
      next: (item) => console.log(`resulting item.. ${item}` ),
      error: (err) => console.log(`error occoured ${err}`),
      complete: () => console.log('Completed')
    })
Enter fullscreen mode Exit fullscreen mode

Let's try error handling and add a check for 0. We'll use a map operator for our error handling. The map takes in the item. We want to execute multiple lines, we need a function body defined with curly braces. That turns our single line arrow function into a multi-line arrow function.
We'll use an if statement to check for a value of 0 and throw an error if a 0 is detected. Otherwise, we return the item.

Note that we need the return keyword in this case. One-line arrow function have implied return.

When we use a multi-line arrow function, we need and explicit return statement.

zero detected resolved

Take
lastly, let's add a take and take only three of the items. We no longer see our error. We take the first three items and complete before the item with the error is emitted.

  from ([20, 15, 10, 5]).pipe(
      tap(item => console.log(`emitted item ... ${item}`)),
      map(item => item * 2),
      map(item => item -10),
      map(item => {
        if(item === 0){
          throw new Error ('Zero detected');
        }
        return item;
      }),
      take(3)
    ).subscribe({
      next: (item) => console.log(`resulting item.. ${item}` ),
      error: (err) => console.log(`error occoured ${err}`),
      complete: () => console.log('Completed')
    })
Enter fullscreen mode Exit fullscreen mode

Take example

app.component.ts file

import { Component, VERSION, OnInit } from '@angular/core';
import {of, from, map, tap, take} from 'rxjs'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  name = 'Angular ' + VERSION.major;

  ngOnInit(){
    from ([20, 15, 10, 5]).pipe(
      tap(item => console.log(`emitted item ... ${item}`)),
      map(item => item * 2),
      map(item => item -10),
      map(item => {
        if(item === 0){
          throw new Error ('Zero detected');
        }
        return item;
      }),
      take(3)
    ).subscribe({
      next: (item) => console.log(`resulting item.. ${item}` ),
      error: (err) => console.log(`error occoured ${err}`),
      complete: () => console.log('Completed')
    })

  }
}
Enter fullscreen mode Exit fullscreen mode

Map operator internals

import { Observable } from 'rxjs';

export function map(fn) {
  // function
  return (
    input // takes an input Observable
  ) =>
    new Observable((observer) => {
      // creates an output Observable
      return input.subscriber({
        // subscribes to the input Observable
        next: (value) => observer.next(fn(value)), // transform item using provided function and emits item
        error: (err) => observer.error(err), // emits error notification
        complete: () => observer.complete(), // emits complete notification
      });
    });
}

Enter fullscreen mode Exit fullscreen mode

Oldest comments (0)