If you have select box and want to make on it search what you will do?
All the source code is here
Use Case of Debounce Operators
The typeahead/autocomplete fields are one of the most common use cases for Debounce Operators.
As the user types in the typeahead field, we need to listen to it and send an HTTP request to the back end to get a list of possible values. If we send HTTP requests for every keystroke, we end up making numerous unneeded calls to the server.
By using the Debounce Operators, we wait until the user pauses typing before sending an HTTP Request. This will eliminates unnecessary HTTP requests.
Create the HTML
<div class="form-group">
<label for="contactMethod">Search</label>
<input [ngModel]="inputCode" (ngModelChange)="search($event)"/>
<select
name="contactMethod"
id="contactMethod"
class="form-control" >
<option *ngFor="let item of list" [value]="item.mal_id">{{ item.title }}</option>
</select>
</div>
Here you will find we have input which we will search by and the select which we will display the data.
- Input has inputCode to display on input and has ngModelChange so will will call
search
function to handle and get the data from API - Select will display only the data which coming from API.
Create the Typescript file to load the list
export class AppComponent {
title = 'angular-debouncer-example';
inputCode = '';
list = [];
constructor(private dataService: DataService) {}
search(event: any): void {
this.dataService.getFilteredByCode(event)
.subscribe((response: ApiResponse) => {
if (response != null) {
this.list = response.results;
}
});
}
}
search
function will call the getFilteredByCode
from the api service DataService
.
Let’s see how that service working.
DataService
export class DataService {
constructor(private http: HttpClient, private debouncerHelperService: DebouncerHelperService) {}
private filterBy(value: string): Observable<ApiResponse> {
return this.http.get<ApiResponse> (`https://api.jikan.moe/v3/search/anime?q=${value}`);
}
getFilteredByCode(code: string): Observable<ApiResponse> {
return this.debouncerHelperService.debouncerOnly<string, ApiResponse>(1000, code, (request) => this.filterBy(request));
}
}
getFilteredByCode
will call the debouncerOnly
from DebouncerHelperService service which will handle the delay to not call the api on every change.
It will wait 1000 then call the 2nd call as in normal it when we enter old
it will call the API 3 time o
, ol
, old
and that’s bad behavior.
Our debouncerOnly
will handle this by passing the 1000 ms and the code which will will search for and the this.filterBy(request)
function.
filterBy
function will get the data from the API.
debouncerOnly how it is working
debouncerOnly<TReq, TRes>(time: number, value: TReq,
callback: (request: TReq) => Observable<TRes>): Observable<TRes> {
const result = new BehaviorSubject<any>(null);
this.debouncer
.pipe(
debounceTime(time),
mergeMap((val: TReq) => {
const obs = val === this.prevData ? of(this.prevData) : callback(val);
this.prevData = val;
return obs;
}),
tap((val: TReq) => {
this.prevData = val;
})
)
.subscribe(val => result.next(val));
this.debouncer.next(value);
return result;
}
- First, we assign a timeout duration (dueTime) to the Debouncetime operator.
- The Debouncetime operator starts counting time after it receives a value.
- If the source observable emits a value before the timeout duration, then counting is reset to zero & started again.
- When the timeout duration elapses the operator emits the last value and the counting stops.
- Counting starts again when the operators receive another value.
- We added compare inside mergeMap to compare the old value with the new value so if it is same as old then do not do any thing.
- NPM package here
- Source code for NPM package here
That is all, now you can use the RXJS Debouncetime as you want all source code is here.