RxJS’ pipe() is both a standalone function and a method on the Observable interface that can be used to combine multiple RxJS operators to compose asynchronous operations. The pipe() function takes one or more operators and returns an RxJS Observable.
pipe
can be used as a standalone method, which helps Angular developers reuse it at multiple places or as an instance method. This article will explain what pipe
is and how to use it in an Angular Application. Additionally, it will show you examples of pipe
using map ,filter
& tap
operators.
RxJs Operators
The operators are an important part of the Rxjs library. They are functions that take an observable as input and transforms it into a new observable without changing the original observable.
In other words, Operator takes in the values from one Observable, and creates a new Observable that emits altered values of the original Observable’s values, without affecting the original Observable.
For Instance:
Map operator takes an observable source as input. It applies a project function to each of the values emitted by the source observable and transforms it into a new value. It then emits the new value to the subscribers.
Filter
operator filters items from the source observable based on some condition and returns the filtered value that satisfies the condition as a new observable and ignores the rest.
The following table shows some of the commonly used RxJS operators;
Using pipe to combine operators
The pipe method accepts operators such as filter
, map, mergeMap
, as arguments. Each argument must be separated by a comma. The order of the operators is important because when a user subscribes to an observable, the pipe executes the operators in a sequence in which they are added.
Can be used in two ways. One as an instance of observable and the other way is to use it as a standalone method.
To use observable you need to import it from the rxjs
library. If you intend to use the pipe
standalone function, then you also need to import it as well. All the operators are available in the library rxjs/operators
.
import { Observable, of, pipe} from ‘rxjs’;
import { map, filter, tap } from ‘rxjs/operators’
Pipe as an instance method
pipe
as an instance method is used as shown below. The operators op1
, op2
etc are passed as the arguments to pipe
method. The output of op1
method becomes input of the op2
operator and so forth.
obs.pipe(
op1(),
op2(),
op3(),
op3(),
)
Here is the example of using pipe with map
& filter
operator.
import { Component, OnInit } from '@angular/core';
import { Observable, of} from 'rxjs';
import { map, filter, tap } from 'rxjs/operators'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: \['./app.component.css'\]
})
export **class** AppComponent implements OnInit {
obs = **new** Observable((observer) => {
observer.next(1)
observer.next(2)
observer.next(3)
observer.next(4)
observer.next(5)
observer.complete()
}).pipe(
filter(data => data > 2), *//filter Operator* map((val) => {**return** val **as** number \* 2}), *//map operator
*)
data = \[\];
ngOnInit() {
**this**.obs1.subscribe(
val => {
console.log(**this**.data)
}
)
}
}
//result
\[6, 8, 10\]
Here is the example of using Pipe
with Map
, Filter
& Tap
operator.
The following example makes use of pipe with map, filter
& tap
operator. RxJS tap() operator is a utility operator that returns an observable output that is identical to the source observable but performs a side effect for every emission on the source observable. It is used mostly for debugging purposes ( for example for logging the values of observable as shown below).
import { Component, OnInit } from '@angular/core';
import { Observable, of, pipe } from 'rxjs';
import { map, filter, tap } from 'rxjs/operators'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: \['./app.component.css'\]
})
export **class** AppComponent implements OnInit {
obs = **new** Observable((observer) => {
observer.next(1)
observer.next(2)
observer.next(3)
observer.next(4)
observer.next(5)
observer.complete()
}).pipe(
tap(data => console.log('tap '+data)), *//tap
* filter(data => data > 2), *//filter
* tap(data => console.log('filter '+data)), *//tap
* map((val) => { **return** val **as** number \* 2 }), *//map
* tap(data => console.log('final '+data)), *//tap*
)
data = \[\];
ngOnInit() {
**this**.obs.subscribe(
val => {
**this**.data.push(val)
console.log(**this**.data)
}
)
}
}
Pipe as a stand alone method
pipe
can be used as a standalone function to compose operators and re-use the pipe
at other places.
For example:
import { Component, OnInit } from '@angular/core';
import { Observable, of, pipe } from 'rxjs';
import { map, filter, tap } from 'rxjs/operators'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: \['./app.component.css'\]
})
export **class** AppComponent implements OnInit {
customOperator = pipe(
tap(data => console.log('tap '+data)),
filter(data => data > 2),
tap(data => console.log('filter '+data)),
map((val) => {
**return** val **as** number \* 2
}),
tap(data => console.log('final '+data)),
);
obs = **new** Observable((observer) => {
observer.next(1)
observer.next(2)
observer.next(3)
observer.next(4)
observer.next(5)
observer.complete()
}).pipe(
**this**.customOperator,
tap(data => console.log('final '+data)),
)
data = \[\];
ngOnInit() {
**this**.obs.subscribe(
val => {
**this**.data.push(val)
console.log(**this**.data)
}
)
}
}
The stand alone pipe can be used as shown below:
customOperator = pipe(
tap(data => console.log('tap '+data)),
filter(data => data > 2),
tap(data => console.log('filter '+data)),
map((val) => {
**return** val **as** number \* 2
}),
tap(data => console.log('final '+data)),
);
obs = **new** Observable((observer) => {
observer.next(1)
observer.next(2)
observer.next(3)
observer.next(4)
observer.next(5)
observer.complete()
})
ngOnInit() {
**this**.customOperator(**this**.obs).subscribe();
}
References
- RxJs Library
- Operators
- Pipe API
- Map API
- Tap API
- Filter API
Read my previous article here and follow me for more more articles on Angular.