Trying to add delay to jQuery AJAX request
Asked Answered
U

3

8

I am trying to delay an AJAX request so that it is sent out 2-3 seconds after the LAST keyup of an input cell.
So far I have managed to delay the requests, but after 2-3 seconds I get one request sent for every keyup in the field...
How can I make jQuery cancel the first ones and just send the last keyup?
Here's the code so far:

$('#lastname').focus(function(){
          $('.terms :input').val(""); //clears other search fields
}).keyup(function(){
    caps(this); //another function that capitalizes the field
    $type = $(this).attr("id"); // just passing the type of desired search to the php file
        setTimeout(function(){ // setting the delay for each keypress
                ajaxSearchRequest($type); //runs the ajax request

        }, 1000);
});

This code above, waits 1 sec then sends 4-5 AJAX requests depending on keypresses. I just want one sent after the last keyup
I have found some similar solutions in StackOverflow that use Javascript, but I have not been able to implement them to my project due to my small knowledge of programming.

[SOLVED] Final working code, thanks to @Dr.Molle:

$('#lastname').focus(function(){
          $('.terms :input').val("");
}).keyup(function(){
    caps(this);
    $type = $(this).attr("id");

    window.timer=setTimeout(function(){ // setting the delay for each keypress
            ajaxSearchRequest($type); //runs the ajax request

        }, 3000);

}).keydown(function(){clearTimeout(window.timer);});

Here's the ajaxSearchRequest code:

function ajaxSearchRequest($type){
                var ajaxRequest2;  // The variable that makes Ajax possible!

                try{
                  // Opera 8.0+, Firefox, Safari
                  ajaxRequest2 = new XMLHttpRequest();
                }catch (e){
                  // Internet Explorer Browsers
                  try{
                     ajaxRequest2 = new ActiveXObject("Msxml2.XMLHTTP");
                  }catch (e) {
                     try{
                    ajaxRequest2 = new ActiveXObject("Microsoft.XMLHTTP");
                     }catch (e){
                    // Something went wrong
                    alert("Browser error!");
                    return false;
                     }
                  }
                }

                ajaxRequest2.onreadystatechange = function(){
                  if(ajaxRequest2.readyState == 4){

                        $result = ajaxRequest2.responseText;
                        $('#resultcontainer').html($result);

                    }}


                var searchterm = document.getElementById($type).value;


                var queryString ="?searchterm=" + searchterm +"&type=" +$type;


                if(searchterm !== ""){

                ajaxRequest2.open("GET", "searchrequest.php" + 
                                 queryString, true);
                ajaxRequest2.send(null);
                }
        }
Unreflecting answered 3/7, 2012 at 9:51 Comment(6)
post the code of ajaxSearchRequestRule
@Rule why is that necessary? You can already see each keyup making a new timeout without cancelling previous ones.Tannen
There is other work around. I can only tell if I know what the function isRule
is there a way to cancel the delay'ed event on .keydown? so if there is no further keydown the keyup event will actually happen?Unreflecting
@Unreflecting the solution is to simply cancel previous (.clearTimeout) timeouts when you set a new timeout. Then the last keyup timeout won't get cancelled.Tannen
Good way. I didn't thought of that +1.Rule
I
17

store the timeout in a variable, so you will be able to clear recent timeouts:

clearTimeout(window.timer);
window.timer=setTimeout(function(){ // setting the delay for each keypress
                ajaxSearchRequest($type); //runs the ajax request

        }, 3000);
Intradermal answered 3/7, 2012 at 9:59 Comment(3)
I'll give you a +1 when you do it without storing that value in a global variable...Beamends
thanx a lot, it worked, here's the final code: ` $('#lastname').focus(function(){ $('.terms :input').val(""); }).keyup(function(){ caps(this); $type = $(this).attr("id"); window.timer=setTimeout(function(){ // setting the delay for each keypress ajaxSearchRequest($type); //runs the ajax request }, 3000); }).keydown(function(){clearTimeout(window.timer);});`Unreflecting
ffs it's example code. It doesn't need a closure for the solution to be apparent.Matsuyama
T
3

What you are trying to do is called debouncing.

Here's a jquery plugin by Ben Alman that does the job.

And underscore.js includes this functionality as well.

There's really no need to hack the ajax request system. Just make sure it's called at the right moment.

Trilogy answered 3/7, 2012 at 12:33 Comment(0)
R
-2

I like the Molle's answer But I would to further improve the performance

var ajaxRequest2;  // The variable that makes Ajax possible!
function getAjaxObject()
{
                try{
                  // Opera 8.0+, Firefox, Safari
                  ajaxRequest2 = new XMLHttpRequest();
                }catch (e){
                  // Internet Explorer Browsers
                  try{
                     ajaxRequest2 = new ActiveXObject("Msxml2.XMLHTTP");
                  }catch (e) {
                     try{
                    ajaxRequest2 = new ActiveXObject("Microsoft.XMLHTTP");
                     }catch (e){
                    // Something went wrong
                    alert("Browser error!");
                   // return false;
                     }
                  }
                }
  return ajaxRequest2;


 }
   getAjaxObject();

    function ajaxSearchRequest($type){



               if(typeof ajaxRequest2 =="undefined" || ajaxRequest2 == false)
                {
                  return;
                }
               ajaxRequest2.abort();

                ajaxRequest2.onreadystatechange = function(){
                  if(ajaxRequest2.readyState == 4){

                        $result = ajaxRequest2.responseText;
                        $('#resultcontainer').html($result);

                    }}


                var searchterm = document.getElementById($type).value;


                var queryString ="?searchterm=" + searchterm +"&type=" +$type;


                if(searchterm !== ""){

                ajaxRequest2.open("GET", "searchrequest.php" + 
                                 queryString, true);
                ajaxRequest2.send(null);
                }
        }

This change will abort an on going ajax request and send a fresh request. It is helpful when you

Typed-> waited 4 sec ->request sent ->typed again (response not received) ->waited 4 second->another request fires

Rule answered 3/7, 2012 at 10:4 Comment(8)
because it's a bad answer? Aborting requests don't help - servers (usually) keep processing queries. The right fix is not to keep sending requests.Beamends
But, it lessens network overhead. And resolves problem of getting multiple responses if you are bit slow in typing.Rule
no, not sending the requests "lessens network overhead". Cancelling an AJAX request just stops the eventual answer from reaching the callback.Beamends
I appreciate any citation to back your argument that "aborting does not lessens network overhead and just stops the data to be received to the callback"Rule
It should be common sense that not sending requests in the first place has lesser network overhead than sending requests but aborting them.Tannen
Of course not sending request has lesser overhead. But cancelling it is better than not cancelling. I think it is also a common sense. I would request @Unreflecting to use it and let you know that if it has practically improved the performance or not. I have used this technique before and seen much improvement practically!Rule
Not sending in the first place is better than sending and cancelling. Which is the obvious and already accepted solution.Tannen
Perhaps, you haven't understood the complete flow yet. Please read the last lines of my reply. If you press few keys, then wait. the request is sent. Then after 4 sec you again type. Then another request will get sent. My code is to stop the old request (if sent and response not received). Basically it is an extended improvement to the accepted answer.Rule

© 2022 - 2024 — McMap. All rights reserved.