Skip to main content

Command Palette

Search for a command to run...

A generalized debounce/search problem

Updated
2 min read
A generalized debounce/search problem
T

Just a guy who loves to write code and watch anime.

The UI problem

We have a login form where username needs to be unique.

When you type the username, we make a request using validateUsername(username: string): Promise<boolean>.

With the result of the request, we update the helper text below the input to either show that the username is available or not. We use the function updateLabel(text: string).

The request can not be made on every keystroke. Otherwise, we'd overload the server.

inputUpdated(text: string) is called on every keystroke.

Now, for this problem, assume debounce is a generalized function. It debounces every single call.

The very naive solution

To show you some pseduo code, we solve this problem by using debounce.

function inputUpdated(text: string) {
  debounce(() => {
    // ...
  });
}

The problem with this solution is for every keystroke, we create a new debounce.

We could solve this by clearing the previous debounce e.g. if we're giving an id or something. In JavaScript, we could use clearTimeout which would be implemented inside the debounce function.

We still have one problem. What if the user types "ab", waits a bit and then types "abc"?

"ab" may not be available, so with the response we update the label to say it is not available. Even though "abc" is available which is what the user sees.

A potential solution

One solution is to abort the previous request. This works if the request is in-flight. But if we already have the response, we can't abort it...

By the way, in JavaScript, you would use AbortController to abort a request.

The solution

We can create a dictionary where we map the user's input (a username) to the result.

Going back to the issue we had where "ab" is not available, but "abc" is, in this case we would look at the dictionary e.g. a Map and see that "abc" is not in there, therefore we can be sure to NOT update the label.

It's better to wait for the right result then to show the user the wrong result.

In the end, we'd have:

abc -> true ab -> false

With abc being in the Map, we know to update the label.

Well, when I think about it, we can always update the label but we decide whether to show it or not based on the Map.