Delay AJAX Searches with JavaScript’s setTimeout

By  on  

I was recently creating a custom Dijit widget that required that a list get filtered during each keystroke instead of using the usual "Submit" button.  The problem I ran into (and had anticipated) was that each keystroke made the list flicker and fire off numerous AJAX requests.  The normal flow was:

D
Da
Dav
Davu // Oops, mistyped!
Dav
Davi
David
David_ // Space
David_W //...and so on

Users that type quickly don't need a list filtered during every keystroke -- that's a waste of client-side processing.  The simple solution is to employ JavaScript's native setTimeout method to delay searches until a given idle-time has passed.  Users who type quickly thus wont bog down the page.

// Add an onChange to the textbox to listen to typing/changes
this.findTextbox.lastValue = "";
var timeout;
dojo.connect(this.findTextbox,"onKeyUp",this,function(){
	// Only fire change if value has changed
	var value = this.findTextbox.get("value");
	if(value != this.findTextbox.lastValue) {
		// Save the "last" value
		this.findTextbox.lastValue = value;
		// Delay before search in the case of typing
		if(timeout) { clearTimeout(timeout); }
		// Start new time out
		timeout = setTimeout(function() {
			// Do the search!
			console.warn("Doing search for " + value + ", time waited");
			// Process....
		},this.findKeyDelay);
	}
});

It's important to store the last value of the input so that "useless" keys like SHIFT, CONTROL, and others don't trigger a restart of the timer.  If the key does change the value of the input element before the timer is met, the timer is clear and restarted!  You'll notice that I do not ensure that a value is present -- that's because I want the field to return all results if the user filters something and then deletes the input!  This type of timer solution will save loads of unwanted processing on both the client and server sides!

Recent Features

Incredible Demos

Discussion

  1. hi david! just curious, why you don’t provide any demo page in this post..?

    • I didn’t include one because the idea of it is simple:

      1. When a key is pressed, and the string is longer than minimum length, start a timeout

      2a. If the value is still the same after that time out, run the search

      2b. If the value isn’t the same, clear the timeout and start it again.

      It’s more the concept that the execution. An example wouldn’t explain much more.

  2. Great tip! What value do you suggest setting the delay to?

    • I don’t have a steadfast, scientific number but I think 500 ms is a good number.

    • Check that — 200 ms is a better one. :)

  3. false

    hi David ! i have tried it at work, but i had prefer to use a periodical method instead of the “onKeyUp” event for checking if the value has changed or not. I think it’s usefull for copy/paste, what do you think about it ?

    I’ve tried it here : http://www.rtl.fr/recherche (french website)

    thanks!

    • Marko

      Even better solution is that onkeyup, oninput and onpaste events you just blur and focus the input element. Like that onchange event is fired, which you can use for checking.

  4. Dan

    This sort of technique will become increasingly important because, I predict, more and more pages will use typeahead not only for search suggestions, but also to update actual page content. I already see examples of typeahead on ecommerce sites showing suggested products as a user types a search phrase.

  5. Shane Burgess

    I had to do this with an App that I was writing as well. I toss a 1 second timeout on it and it improved the slickness 100 fold. :)

    • Yep, I’ve found that I’m doing this more often than not.

  6. jeff

    This idea has a little problem attached to it.
    I’m not sure if you noticed.

    Lets say you set findKeyDelay to 1000ms.
    Lets say, user types word “audi” and typing takes less than 1 sec.
    In such case your search may get stuck …

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!