RxJS: Debounce explained

Posted by Tomasz Smykowski on

RxJS stands for Reactive Extensions for JavaScript. It is a great library to handle flow of items received by your application. Today you will learn what is one of the most commonly used RxJS operator: debounce

The documentation offers a nice diagram with circles that is self-explanatory:

But what does it really mean? Let's forget about the diagram for a moment.

The analogy

Imagine a scout comes back with reports from the war zone. Every time he leaves a papyrus with all information necessary. He is a fast scout, so he leaves multiple reports per day. Also, you know that he returns reports so fast, only when there is nothing really going on. So when he stops coming back fast, it means things are happening. Since you are busy working with other tasks like preparing your swordsmen, you decide to read reports only when he won't come back for a day. When it happens, you throw away all old reports and read the last one he delivered. That way you are always up to date.

This is how RxJS debounce works. It looks like this:

Balls represent items coming to a debounce operator. Every new item causes previous items to be kicked out. When there are no new items for some time, the last item that arrived is returned. You can think about it as grouping a sequence of items.

How to translate this analogy to programming? Why an app should ignore annoyingly frequent events, and only process the last event that happened before silence?

The example

RxJS debounce is very useful when you have to limit input events but also react to the last one. So for example lets say you have an input field, where user types in a city name. You decide to show a suggestions list when he does it. Each key he presses you fetch suggestions from an API.

However, it means you have to send tens of requests. And the user will likely not see results of all of them, because before you have an opportunity to show suggestions, he already typed five more letters in.

So you decide to use debounce to ignore user input, until there is a one-second gap in the steady flow of characters.

The logic you want to introduce looks like this:

When a new key is pressed:

- check if there were no keys pressed for one second

- if yes, show suggestions list

The formal way to write it down with RxJS like this:

         () => interval(1000)
      x => showSuggestions(x)

As you can see it is pretty complex syntax. It is because RxJS offers more operators than debounce and ways to combine them. You can think of pipe section as a decision-making how to handle incoming events, and subscribe what to do with events that pipe returns.

There are other operators you can use in the pipe section. However, there are two interesting things about debounce I want to share with you before this article finishes.

Interesting facts

If you want to work with time intervals, you may find debounceTime better for you.

If you want to lower overheat of repetitive actions even more, you can add also distinctUntilChanged operator to your pipe.

Also check out:

Part 1: Rx JS throttle