Ajax requests when users stop typing

I was tackling a problem the other day related to triggering ajax requests as a user was typing in an input field. Sometimes you can just fire off the request on the blur event, but other times you want to fire it off from a keypress event. Sending xhr requests on every keypress can quickly overload your server and/or database. More often than not, if a user is typing, you can wait until they are done, or for a pause in their button mashing to send the request. This saves your server from getting hammered by un-needed requests, but still gives the user the experience desired.

A simple approach to this is wrapping your method that handles the particular ajax request with another simple method that records the time when they key was pressed, and queues up the ajax request method using setTimeout. Here’s an example below:

Example = {
   interval : 1000,
   lastKeypress : null,
   interceptKeypress : function() {
      this.lastKeypress = new Date().getTime();
      var that = this;
      setTimeout(function() {
         var currentTime = new Date().getTime();
         if(currentTime - that.lastKeypress > that.interval) {
            that.sendRequest();
         }
      }, that.interval + 100);
   },
   sendRequest : function() {
      //Perform xhr request
   }
}

The Example.interceptKeypress() method now becomes what you tie the keyup event of your text input to instead of going straight to the Example.sendRequest() method. The current time is recorded, and then Example.sendRequest() is queued up using setTimeout() and a closure to handle scoping and ensure that enough time has passed since the last keyup event (100 ms is added to the current time as a buffer).

This approach can easily be added onto existing event handlers if you find you’re sending too many requests in particular situations, or for any type of event handling where you want to limit when/how often it is fired. Hope this benefits some people!

  • del.icio.us
  • Digg
  • Facebook
  • Reddit
  • Twitter
  • Yahoo! Buzz
and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

9 Comments

  1. ws
    Posted November 30, 2007 at 6:55 am | Permalink

    Thanks for the code! I’ve been trying to do something like this for a while.

    FYI. there is a small typo in your code. The second Date().getTime() is typed Date.getTime().

    Again.. Thanks for the code.

  2. Posted November 30, 2007 at 12:07 pm | Permalink

    Ah, so it is. Fixed now, thanks.

  3. adamzap
    Posted February 27, 2008 at 5:31 am | Permalink

    w00t just what I needed thanks

  4. Joe
    Posted October 7, 2009 at 12:03 pm | Permalink

    I’m having much more success without the 100 ms interval on the setTimeout. Placed an alert() in the sendResponse for testing. With the buffer, I’m seeing multiple alert fires where I should not, however seems to work fine without that buffer. Any insight?

  5. brad
    Posted October 7, 2009 at 12:12 pm | Permalink

    I believe the buffer was needed only for a specific version of IE, maybe 6.5, but I don’t recall exactly. I can’t imagine why adding 100 ms to the timeout callback would cause multiple events to be fired. What event are you binding your callback to, the keyup?

    On a related note, I have found that an additional feature is needed to ensure xhr callbacks are processed in the correct order. A local counter is needed on the object that increments every time your “interceptKeypress” is fired. Then when you call the xhr request function, you have to pass the current value of that counter, and then check it in the xhr callback to ensure what is passed in is the same as the current value of the counter. Without this I was seeing issues where the most recent xhr request would fire, get called back, and then a previously called request would come back afterwards and trump it.

  6. Secundes
    Posted October 20, 2009 at 12:58 am | Permalink

    Great, it solves my problem.
    Thanks

  7. Posted April 6, 2010 at 4:26 pm | Permalink

    As I smashed my head against the wall for the better part of an hour, I finally landed on the exact answer I needed. Brilliant.

  8. Posted December 11, 2010 at 8:26 am | Permalink

    I was implementing something similar in jQuery, but these days i’m finding excuses to use a delay before ajax in most of the UI stuff i do.

    I packaged this up into a plugin available here for jquery that can be used with the normal $.ajax calls.

  9. Posted June 8, 2011 at 9:05 am | Permalink

    Old solution to old problems in new projects. Great code!!

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Page optimized by WP Minify WordPress Plugin