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.
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
first<T, D>(predicate?: (value: T, index: number, source: Observable<T>) => boolean, defaultValue?: D) : OperatorFunction<T, T | D>
Where
predicate: is the condition to match
defaultValue: is the value to emit if no value matches the condition
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.
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
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.
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.
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
src = of().pipe(first());
***Error
no elements in sequence
The following emits the default value 100
src = of().pipe(first(val => true, 100));
***Console
100
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.
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
last<T, D>(predicate?: (value: T, index: number, source: observable<T>) => boolean, defaultValue?: D) :OperatorFunction<T, T | D>
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.
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
src = of(1, 2, 3, 4, 5).pipe(last(val => val < 3));
***Console**
2
Returns an error as no value matches the condition.
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.
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
src = of().pipe(last());
***Error
no elements in sequence
The following emits the default value 100
src = of().pipe(last(val => true, 100));
***Console
100
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.
The Single operator emits a single value that meets the condition.
single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T>
Where
predicate is the condition
Emits 3 as it matches the condition.
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.
src = interval(1000).pipe(single(val => val == 3));
**Console*
Raises error notification as there are more than one value that satisfies the condition.
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.
src = of(1, 2, 3, 4, 3).pipe(single(val => val == 5));
*Console*
undefined
Single without any predicate matches all values. Hence the error.
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
src = of(1).pipe(single());
**Console**
1
Source is empty, Hence it raises error notification.
src = of().pipe(single());
**Console***
ERROR
Error: no elements in sequence