views:

458

answers:

5
$(document).ready(function() {

    $('#domain').change(function() {

        //

    });

});

The code inside the change function will basically send ajax request to run a PHP script. The #domain is a text input field. So basically what I want to do is to send ajax requests as user types in some text inside the text field (for example search suggestions).

However, I would like to set a time interval in order to lessen the load of PHP server. Because if jQuery sends AJAX request every time user adds another letter to the text field it would consume lots of bandwidth.

So I would like to set let's say 2 seconds as an interval. The AJAX request will be fired every time the user types a letter but with maximum frequency of 2 seconds.

How can I do that?

+4  A: 
$(document).ready(function() {

    $('#domain').change(function() {

        if(!ajaxQueue) {
           ajaxQueue = setTimeout(function() { 
              /* your stuff */
              ajaxQueue = null;
          }, 2000);
        }

    });

});
David Hedlund
Where is ajaxQueue declared?
svinto
This would only fire once.
eduncan911
That's the brilliance, it's defined right in the setTimeout. Until then it will be undefined (and, thus, falsey). It's effectively the same as writing `var ajaxQueue = null;` right before the `$(document).ready(...)`.
thenduks
This is actually a quite elegant solution. Definitely better than tracking the number of milliseconds between events.
Vincent Ramdhanie
Hmm. The ajax call isn't getting executed even once with this code.
Richard Knop
@thenduks: Not it's not, it's never declared, thus it'll end up in the window object and that's a bad thing.
svinto
@svinto: a variable that is introduced without 'var', will be a global variable. that is the same thing as putting it in the window object, yes, but that's exactly what a global variable is, in js. if you write var `a = 'test';` in the global scope of your code, you'll be able to access that at `window.a` as well. it's fairly standard practice, i can't say it's a bad thing, but of course, it's not very self-documenting code
David Hedlund
@eduncan911: it would fire more than once, actually. once it has fired, it'll set itself to null, which means the next time `change` is triggered, `ajaxQueue` will be falsey, and a new timeout will be set. if it had not fired, though, it wouldn't register a new timeout, which is exactly the desired result
David Hedlund
+2  A: 
$(function() {
  var timer = 0;
  $("#domain").change(function() {
    clearTimeout(timer);
    timer = setTimeout(function(){
      // Do stuff here
    }, 2000);
  });
});
svinto
+1  A: 

What you really want to do is check how long since the last change event so you keep track of the number of milliseconds between events rather than make a call every 2 seconds.

$(document).ready(function() {

    var lastreq = 0; //0 means there were never any requests sent
    $('#domain').change(function() {
         var d = new Date();
         var currenttime = d.getTime(); //get the time of this change event
         var interval = currenttime - lastreq; //how many milliseconds since the last request
         if(interval >= 2000){ //more than 2 seconds
            lastreq = currenttime; //set lastreq for next change event
            //perform AJAX call
         }

   });

});
Vincent Ramdhanie
Doesn't this need a mop-up function to send the last update to the server?
Bell
@Bell it does not. It is tied to the change event so if this change event is more than 2 seconds since the last change event then it sends the call otherwise it just ignores the event. Although I think that @d's solution is cleaner and its the one I would go with.
Vincent Ramdhanie
What about if I type two characters, and the second one hits during the time when it should not send... but i never type the third char to trigger it again?
Ape-inago
A: 

Off the top of my head without trying this in a browser. Something like this:

$('#domain').change(function() {

    if (!this.sendToServer) { // some expando property I made up
     var that = this;
     this.sendToServer = setTimeout(function(that) {
      // use "that" as a reference to your element that fired the onchange.
      // Do your AJAX call here
      that.sendToServer = undefined;
     }, yourTimeoutTimeInMillis)
    }
    else {
     clearTimeout(this.sendToServer);
    }
});
nickyt
+1  A: 

two variables, charBuffer, sendFlag

  1. Use a setTimeout to have a function be called every two seconds.
    • This function checks if the buffer has stuff in it.
    • If it does, it sends/empties the stuff and clears the sent flag (to false).
      • and It should also clear the timeout, and set it again
    • else it sets the flag (to true).
  2. Everytime the user hits a key, store it in the buffer.
    • if the sent flag is clear (it's false), do nothing.
    • else (it's true) send/empty the stuff currently in the buffer and clear the flag (to false),
      • and It should also clear the timeout, and set it again

This will make it so that the first time you press a key, it is sent, and a minimum of 2 seconds must pass before it can send again.

Could use some tweaking, but i use this setup to do something similar.

Ape-inago
In this case, the text input field could be the buffer... so much of this could be redundant.
Ape-inago