Using Debouncing vs Throttling & implementation in Angular

Using Debouncing vs Throttling & implementation in Angular

Purpose: To optimize the performance of the web app, How? By limiting the rate of function calls for eg. API calls.

For example - search bar -> Input event {value changes - subscribe}

Suppose we're entering some letters in the search bar, there we see that for every letter that we enter, API is getting called. If we search for "Apple iPhone", 11 times we'll be calling the API. And if we've got multiple / thousands of users on our website, so for them the load on the network would be heavy & API calls would get multiplied accordingly.

Solution => We can limit the API calls.

Debouncing :*It suggests only making an API / function call when the time difference b/w 2 input events is greater than a time value* ( for eg. let's assume 400ms ), this way we'll save a lot of API calls.

Now, let's write some basic code & make a search bar. The HTML will look like this -

<div class="search">
  <p>Search</p>
  <mat-form-field appearance="outline" style="width: 70%;">
    <input [formControl]="searchText" autocomplete="off" type="text" matInput placeholder="Enter your search text here">
  </mat-form-field>
</div>

To incorporate debouncing, we need to make changes in the component (.ts) file. I've used two RxJS operators here - debounceTime() & distinctUntilChanged(), so when the time difference b/w 2 inputs events > 400 ms then only my method will be called.

  • The role of debounce time / throttle time is to wait for sometime, but distinctUntilChanged() when used with debouncing can be a lethal combination altogether as it makes sure that the user is not hitting the server with same kind of requests all the time, Under the hood it backtracks & always compares the current emission vs the previous emission, when they're different only then it fires off the request!
ngOnInit() {
    this.searchText.valueChanges.pipe(debounceTime(400),distinctUntilChanged()).subscribe((res) => {
      console.log("res", res);
      // any BE api call can be made here
    }, (err) =>{
      console.log(err);
    });
  }

Throttling: Suppose there are lots of events happening, it suggests only making a function call after a certain limit of time. Suppose we're initially calling the API, now after 300ms, the next call will be made. During the gap time, the events will be ignored & no API call will be made before the defined limit. Hence, the difference b/w 2 API calls is the time limit that we define.

 this.searchText.valueChanges.pipe(throttleTime(400),distinctUntilChanged()).subscribe((res) => {
      console.log("res", res);
    } , (err) => {
      console.log(err);
    });

Why are we doing this?
-> To tackle the load on the DOM since we may be using multiple DOM Events & network calls & we don't want a bad UX.

So, What do we use?

  • For Search functionality: In most e-commerce websites, for eg. Amazon, and Flipkart the concept of debouncing has been implemented. As users type very fast generally & they stop only when they complete a word, the difference is calculated & checked.

  • Upon resizing the window :
    -> To log how often / frequently the user is triggering the resize event - throttle - because this makes sure that after every 100ms or defined interval we're hitting the API { max coverage}.

    -> To track: how many times the window has been resized - debounce, because we're stopping once we leave the mouse or stop resizing. This way we can keep track of the count. If we rely on throttle here, then we may miss the count if we're resizing within a certain time interval.

  • Handling multiple & frequent clicks (Shooting Game, Duck Hunt as I used to play on TV ;) )

    -> Debouncing: use when we want to limit the no. of actions that happen on a click, for eg. once the user releases the click & when the difference b/w the 2 click events/calls have passed a certain limit then the function call will be made.

    -> Throttling: Use when only after a certain time limit do you want to make a function call. For eg. a user may click as many times as he wants but in a game, he'll be able to use the machine gun only after 500ms.

What is better?

No specific answer because it depends entirely on the use case!

Credits -

https://www.youtube.com/watch?v=tJhA0DrH5co

https://css-tricks.com/the-difference-between-throttling-and-debouncing/

https://rxjs.dev/api/operators/distinctUntilChanged

Github Repo Link -

https://github.com/niharika293/debounce-throttle