In the tutorial, let us learn the First, Last & Single RxJs operators in Angular Observable. All three operators use the predicate (condition) to check the values of the source observable. The first emits the first matching value, the Last emits the last matching value & the Single emits only if a single value matches the predicate.
First Operator
The first operator emits the first value that meets the condition. If no condition is specified, then it will emit the first value it receives.
Syntax
1 2 3 | first<T, D>(predicate?: (value: T, index: number, source: Observable<T>) => boolean, defaultValue?: D) : OperatorFunction<T, T | D> |
Wherepredicate
: is the condition to matchdefaultValue
: is the value to emit if no value matches the condition
- Emits the first value if no predicate is present
- Emits the first matching value if the predicate is present
- Closes the stream after emitting a value
- If the source completes before emitting any matching value, then it raises the error notification.
Example
In the following example, we create an observable using the of operator. The first operator here emits the first value it receives i.e 1
and then it completes.
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 28 29 30 | import { Component, VERSION } from "@angular/core"; import { timer, interval, of } from "rxjs"; import { first } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { src = of(1, 2, 3, 4, 5).pipe(first()); id = Date.now(); constructor() {} ngOnInit() { console.log("Component Created " + this.id); this.src.subscribe(value => { console.log(value); }); } } *** Result **** 1 |
Emits the first value that matches
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(first(val => val > 3)); **Result** 4 |
The following code returns an error as no value matches the condition.
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(first(val => val > 10)); ***Error no elements in sequence |
But first with the default value, will emit the default value if no value matches the condition.
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(first(val => val > 10,100)); ***Console** 100 |
The following also results in an error, as the source does not emit any values
1 2 3 4 5 6 7 | src = of().pipe(first()); ***Error no elements in sequence |
The following emits the default value 100
1 2 3 4 5 6 7 | src = of().pipe(first(val => true, 100)); ***Console 100 |
First Vs Take(1)
The first()
(without condition & default value) and take(1)
returns the first value they receive from the source and closes the observable.
But they have a difference in behavior when the source does not emit anything. The first()
send an error notification, while take(1)
will not emit anything, but closes the observable.
Last Operator
The last operator emits the last value that meets the condition. If no condition is specified, then it will emit the last value it receives.
Syntax
1 2 3 | last<T, D>(predicate?: (value: T, index: number, source: observable<T>) => boolean, defaultValue?: D) :OperatorFunction<T, T | D> |
- Waits for the source to complete before emitting the value
- Emits the last value if no predicate is present
- Emits the last matching value if the predicate is present
- Closes the stream after emitting a value
- If the source completes before emitting any matching value, then It raises the error notification.
Example
In the following example, we create an observable using the of operator. The last operator here emits the last value it receives i.e 5
and then it completes.
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 28 29 | import { Component, VERSION } from "@angular/core"; import { timer, interval, of } from "rxjs"; import { last } from "rxjs/operators"; @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent { src = of(1, 2, 3, 4, 5).pipe(last()); id = Date.now(); constructor() {} ngOnInit() { console.log("Component Created " + this.id); this.src.subscribe(value => { console.log(value); }); } } **Console ** 5 |
Emits the last value that matches the predicate
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(last(val => val < 3)); ***Console** 2 |
Returns an error as no value matches the condition.
1 2 3 4 5 6 7 8 9 | src = of(1, 2, 3, 4, 5).pipe(last(val => val < 0)); *** Console ***** ERROR Error: no elements in sequence |
But with a default value, it will emit the default value if no value matches the condition.
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(last(val => val < 0,0)); ***Console** 100 |
The following also results in an error, as the source does not emit any values
1 2 3 4 5 6 | src = of().pipe(last()); ***Error no elements in sequence |
The following emits the default value 100
1 2 3 4 5 6 7 | src = of().pipe(last(val => true, 100)); ***Console 100 |
Last Vs TakeLast(1)
The last()
(without condition & default value) and takeLast(1)
returns the last value they receive from the source observable.
But they have a difference in behavior when the source does not emit anything. The last()
send an error notification, while takeLast(1)
will not emit anything, but closes the observable.
Single
The Single operator emits a single value that meets the condition.
- The Single operator waits for the source to complete before emitting the value
- Emits a single value that meets the condition
- If more than one value satisfies the condition, then it raises an error notification
- If no value satisfies the condition, then it emits the value
undefined
- Raises the error notification, if the source does not emit any value.
Syntax
1 2 3 | single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T> |
Wherepredicate
is the condition
Examples
Emits 3
as it matches the condition.
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 5).pipe(single(val => val == 3)); **Console 3 |
Waits for the observable to finish. Hence the following will never emit a value.
1 2 3 4 5 | src = interval(1000).pipe(single(val => val == 3)); **Console* |
Raises error notification as there are more than one value that satisfies the condition.
1 2 3 4 5 6 7 8 9 | src = of(1, 2, 3, 4, 3).pipe(single(val => val == 3)); **Console** ERROR Sequence contains more than one element |
If the source does not emit any matching values, then the Single operator emits undefined
. Note that it does not emit error notification.
1 2 3 4 5 6 | src = of(1, 2, 3, 4, 3).pipe(single(val => val == 5)); *Console* undefined |
Single without any predicate matches all values. Hence the error.
1 2 3 4 5 6 7 | src = of(1, 2, 3, 4, 3).pipe(single()); ***Console*** ERROR Sequence contains more than one element |
Source contains single value and Single without predicate. Emits the value
1 2 3 4 5 6 | src = of(1).pipe(single()); **Console** 1 |
Source is empty, Hence it raises error notification.
1 2 3 4 5 6 7 8 | src = of().pipe(single()); **Console*** ERROR Error: no elements in sequence |
If the source does not emit any matching values, then the Single operator
emits als an error notification.
src = of(1, 2, 3, 4, 5).pipe(last(val => val < 0,0));
***Console**
100
it's 0 in the console, not 100