⚠️ This lesson is retired and might contain outdated information.

Debounce user input to avoid repeated Ajax requests

Shane Osbourne
InstructorShane Osbourne
Share this video with your friends

Social Share Links

Send Tweet

When accepting user input and converting it into a request that talks to the outside world, we can often end up in a situation where responses are no longer relevant. This is a common case in type-ahead style input fields - we would only want to call an external search API after the user has stopped typing for a short amount of time. In this lesson we’ll see how we can begin to combine RxJS operators to solve such problems.

Instructor: [00:00] In this application, if I type a single character, it makes a network request to an API. It returns some data. We display it on the screen, which all looks good.

[00:13] If I type "skull," it gives us one search result, but we had an additional four requests that we didn't need to make. Why is this happening? Back in the component, this input field has an unchanged handler that for every change will call our search function.

[00:36] This is an action creator that we have bound using React Redux. It ends up producing an action of type search.

[00:47] The way our epic works right now is that for every single action that comes through of this type, it makes it through to this switchMap, which will keep executing this function, returning no observables, and unsubscribing to previous ones until we get to the point that one completes and we end up with the search results here.

[01:07] This can end up flooding a backend with API requests that are not really needed. Instead, what we'd like to do is wait for a small window of time where the user has stopped typing, then go off and make a network request there.

[01:22] As they start typing again, we may want to cancel. The point is we shouldn't be making any requests at all if they are typing really quickly. This type of operation is what RxJS was designed for.

[01:33] This particular problem can be solved with something called debounceTime. We'll import this from rxjs/operators. You see we place it directly after the OfType filter. This will handle filtering the action stream to only include actions of type search.

[01:52] Then this will subscribe to that new stream, but it will have an internal timer. Every time it sees a value, it will reset its timer. The timer's based on the number we give here. It's in milliseconds.

[02:04] What will happen here is if we only search for a single character, the element will make it into this observable. After 500 milliseconds, we'll make it down here.

[02:16] If another action makes it through here before our internal timer has elapsed and debounceTime resets, it drops the previous value. It waits to see if 500 milliseconds passes again.

[02:31] This is what's known as a lossy strategy, meaning we're not aggregating anything. We're not keeping a buffer of any previous values. We're just waiting until this window of time has passed where there have been no events.

[02:45] Only at that point we then emit the previous event that we saw. That's it. With a single line, we can go back to the browser. We can try the same experiment again. We try and search for "skull." You can see only got a single network request.