The take, takeUntil, takeWhile & takeLast operators allow us to filter out the emitted values from the observable. The take(n) emits the first n values, while takeLast(n) emits the last n values. The takeUntil(notifier) keeps emitting the values until it is notified to stop. takeWhile(predicate) emits the value while values satisfy the predicate. All of the stops emitting once done.
Table of Contents
Take
Take operator emits the first n number of values before completing. Any reminder values are ignored.
Syntax
take(n)
Where n
is the maximum number of values to emit.
If the source emits more than n
values, then take
emits only n
values and completes
If the source emits less than n
number of values, then take
emits all of them before completing.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import { Component, VERSION } from "@angular/core"; import { of } from "rxjs"; import { take } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { obs = of(1, 2, 3, 4, 5).pipe(take(2)); ngOnInit() { this.obs.subscribe(val => console.log(val)); } } ****Console ****** 1 2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | export class AppComponent { takeFive = interval(1000).pipe(take(5)); ngOnInit() { this.takeFive.subscribe(val => console.log(val)); } } ****Console ****** 0 1 2 3 4 |
TakeUntil
The takeUntil
operator returns an Observable that emits value from the source Observable until the notifier
Observable emits a value.
Syntax
1 2 3 | TakeUntil(notifier: Observable): Observable |
We must pass a notifier observable as the argument to the TakeUntil Operator
TakeUntil emits the values from the Source Observable as long as it does not receive any value from the notifier observable
When the notifier emits a value, the TakeUntil completes the Source observable.
If the notifier completes without emitting any value, then the TakeUntil keeps emitting values from the source and completes when the source completes.
Example
In the example below, we create a notifier observable
1 2 3 | notifier= new Subject(); |
The notifier observable emits a value , when use clicks on the stop button.
1 2 3 4 5 6 | stopObs() { this.notifier.next(); this.notifier.complete(); } |
Use the takeUntil in the source observable as shown below
1 2 3 | obs = interval(1000).pipe(takeUntil(this.notifier)); |
Run the app. The source observable stops when you click on stop button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import { Component, VERSION } from "@angular/core"; import { of, interval, Subject, Observable } from "rxjs"; import { take, takeUntil, tap } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { notifier = new Subject(); obs = interval(1000).pipe(takeUntil(this.notifier)); ngOnInit() { this.obs.subscribe(val => console.log(val)); } stopObs() { this.notifier.next(); this.notifier.complete(); } } |
1 2 3 4 5 6 7 | <h1>TakeUntil Example</h1> <button (click)="stopObs()">Stop</button> <br> |
One of the use cases of takeUntil is to automatically unsubscribe all the observables. You can refer to it from the tutorial on Unsubscribing from an observable.
TakeWhile
TakeWhile operator will keep emitting the value from the source observable as long as they pass the given condition (predicate). When it receives a value that does not satisfy the condition it completes the observable. No further values are emitted even if they satisfy the condition.
Syntax
1 2 3 4 | takeWhile(predicate: function(value, index): boolean, inclusive?: boolean): Observable |
Where predicate
is the condition.
If inclusive
is true, then the emits the value, which does not pass the condition before terminating the observable.
Example
In the code below takeWhile
tests the condition val < 3
against the incoming values. When it receives the value 3, which does not satisfy the condition, the observable completes. It does not emit any further values although the stream still has values that satisfy the condition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import { Component, VERSION } from "@angular/core"; import { of, interval, Subject, Observable } from "rxjs"; import { take, takeUntil, takeWhile, tap } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3) .pipe( takeWhile(val => val < 3) ); ngOnInit() { this.obs.subscribe(val => console.log(val)); } } *** Console *** 1 2 |
With inclusive is set to true, takewhile also emits the value 3
before completing the observable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | export class AppComponent { obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3) .pipe( takeWhile(val => val < 3, true) ); ngOnInit() { this.obs.subscribe(val => console.log(val)); } } *** Console *** 1 2 3 |
Example
1 2 3 4 5 6 7 8 9 10 11 12 | evenNumbers = of(2, 4, 6, 3, 8) .pipe(takeWhile(n => n % 2 == 0)) .subscribe(val => console.log(val)); **Console *** 2 4 6 //8 is not emitted |
TakeWhile Vs Filter
Both takeWhile
& filter
uses the condition to filter out the incoming stream. Both allows only the matching values to pass through discarding the others.
The difference is that takeWhile
discards the rest of the stream, when it receives the first value that does not satisfy the condition (If the inclusive
is set to true
, then it also emits the last value even when it does not satisfy the condition). The filter
operator never stops the observable.
The following example, filter operator does not stop when it receives the value 3. But it discards it and continues further until the stream itself completes.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3) .pipe( filter(val => val < 3, true) ); ngOnInit() { this.obs.subscribe(val => console.log(val)); } ***Console **** 1 2 1 2 1 2 |
TakeLast
TakeLast operator emits the last n number of values from the source observable.
Syntax
1 2 3 | takeLast<T>(n: number) |
Where n
is the maximum number of values to emit.
To know the last n
number of values, the TakeLast
needs to wait for the source to complete. Hence if the source never completes, then TakeLast
will never emit a value.
When the stream completes, the takeLast
will
- emits the last
n
number of values - if the source emits less than the n number of values then it emits all of them
- stream completes immediatly
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import { Component, VERSION } from "@angular/core"; import { of, range, Observable } from "rxjs"; import { takeLast } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { obs = range(1, 100).pipe(takeLast(3)); ngOnInit() { this.obs.subscribe(val => console.log(val)); } } ***Console**** 98 99 100 |
Angular Tutorials is Amazing.
All Rxjs Operators explain to the point.
After reading so many blogs I found this far better then others