1 min read

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.

About the author

For the last decade, Shady Nagy has worked with a variety of web technologies. He is currently focused on code quality. On his day to day job, he is working as a team leader engineer. As a digital nomad, he is living where the WiFi and sun are 😎
Do you want to know more? Visit my website!