35

I'm trying to understand throttleTime vs debounceTime and which one is to be used when?

I have an upvote button that makes an API request to the backend (which counts the votes). User can submit button multiple times, but I'd like to limit the times per second button can be pressed.

I know throttleTime and debounceTime operators can do that, but which one should I choose?

const upvoteClicks = fromEvent(this.el.nativeElement, 'click')
   .pipe(debounceTime(500))
   .subscribe(() => this.myService.postUpvote(this.postId));
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Cleave Kokle
  • 373
  • 1
  • 3
  • 5

3 Answers3

58

I think in your case throttleTime works a little bit better, because you want to make the api request as soon as user clicks the button.

Both throttleTime and debounceTime ignore the events which come in the meantime, but throttleTime emits right away, while debounceTime waits for additional delay.

You can visually see that very well at https://rxmarbles.com enter image description here

enter image description here

What is more, throttleTime vs debounceTime in RxJS article provides a good overview of both operators.

Harijs Deksnis
  • 1,366
  • 1
  • 13
  • 24
12

(A more simple answer)

Say a user clicks a button that triggers a request (example):

Throttle time = can limit the number of clicks so only 1 goes through every second (prevents button spamming)

Debounce time = can add a delay before each request goes through (you press the button then nothing happens for 1 seconds, then your request goes through)

1 second was just an example. You can enter whatever you'd in the debounceTime() or throttleTime() - in ms

Collin
  • 394
  • 5
  • 14
  • 1
    While this is correct, you only explain the 'when' and not 'what'. In OP's example the button press represents a like or vote. Let's say the user voted on a 1st post and immediately changed his mind and voted for the 2nd post/person/whatever. Using `throttleTime` you'd register a like for post 1 and using `debounceTime` you'd register a like for post 2. Neither implementation is superior to the other, but it's an important difference to keep in mind. – T_D Jun 10 '21 at 14:57
2

The accepted answer has clearly pointed out the difference between throttleTime and debounceTime.

However I'd like to bring up a slightly different option in your particular situation, that is exhaustMap. exhaustMap is an operator that ignores every new projected Observable if the previous one has not yet completed. So the first API request to backend has to be completed before the user can execute it the second time. It's useful if the API data is bouncing back very slowly, slower than the fixed time you set, it won't trigger any further API call until the previous one completed. You can read more about exhaustMap here.

const upvoteClicks = fromEvent(this.el.nativeElement, 'click')
   .pipe(
      exhaustMap(() => this.myService.postUpvote(this.postId))
    )
   .subscribe(() => console.log('upvoted!'))
KienHT
  • 1,098
  • 7
  • 11