13

I am trying to add a delay to a repeatable query.

I found out that .delay is not the one to use here. Instead, I should go with setInterval or setTimeout. I tried both, without any luck.

Here's my code:

<?php 
include("includes/dbconf.php");

$strSQL = mysql_query("SELECT workerID FROM workers ORDER BY workerID ASC");
while($row = mysql_fetch_assoc($strSQL)) {
?>
<script id="source" language="javascript" type="text/javascript">

  $(setInterval(function ()
  {
    $.ajax({                                      
      cache: false,
      url: 'ajax2.php',        
      data: "workerID=<?=$row['workerID'];?>",
      dataType: 'json',    
      success: function(data)
      {
        var id = data[0];              //get id
        var vname = data[1];           //get name
        //--------------------------------------------------------------------
        // 3) Update html content
        //--------------------------------------------------------------------
        $('#output').html("<b>id: </b>"+id+"<b> name: </b>"+vname);
      } 
    });
  }),800); 

  </script>
<?php
}
?>
<div id="output"></div>

The code works fine, it outputs the result as asked. It's just loads without the delay. The timout and / or interval doesn't seem to work.

Anybody knows what I am doing wrong?

cssyphus
  • 37,875
  • 18
  • 96
  • 111
Jeroen
  • 147
  • 1
  • 1
  • 6

4 Answers4

26

I've never understood why people always add their AJAX requests in intervals rather than letting the successful AJAX calls just call themselves, all the while risking severe server load through multiple requests and not just making another call once you had a successful one come back.

In this light, I like to write solutions where the AJAX calls just call themselves on completion, something like:

// set your delay here, 2 seconds as an example...
var my_delay = 2000;

// call your ajax function when the document is ready...
$(function() {
    callAjax();
});

// function that processes your ajax calls...
function callAjax() {
    $.ajax({
        // ajax parameters here...
        // ...
        success: function() {
            setTimeout(callAjax, my_delay);
        }
    });
}

I hope this makes sense! :)

Update:

After reviewing this again, it's been brought to my attention that there was also a problem in the PHP code in the original question that I needed to clarify and address.

Although the script above will work great in creating a delay between AJAX calls, when added to the PHP code in the original post the script will just be echo'd out as many times as the number of rows the SQL query selects, creating multiple functions with the same name and possibly making all AJAX calls simultaneously...not very cool at all...

With that in mind, I propose the following additional solution - create an array with the PHP script that may be digested by the JavaScript one element at a time to achieve the desired result. First, the PHP to build the JavaScript array string...

<?php 
    include("includes/configuratie.php");
    $strSQL = mysql_query("SELECT workerID FROM tWorkers ORDER BY workerID ASC");

    // build the array for the JavaScript, needs to be a string...
    $javascript_array = '[';
    $delimiter = '';
    while($row = mysql_fetch_assoc($strSQL))
    {
        $javascript_array .= $delimiter . '"'. $row['workerID'] .'"'; // with quotes
        $delimiter = ',';
    }
    $javascript_array .= ']';
    // should create an array string, something like:
    // ["1","2","3"]
?>

Next, the JavaScript to digest and process the array we just created...

// set your delay here, 2 seconds as an example...
var my_delay = 2000;

// add your JavaScript array here too...
var my_row_ids = <?php echo $javascript_array; ?>;

// call your ajax function when the document is ready...
$(function() {
    callAjax();
});

// function that processes your ajax calls...
function callAjax() {
    // check to see if there are id's remaining...
    if (my_row_ids.length > 0)
    {
        // get the next id, and remove it from the array...
        var next_id = my_row_ids[0];
        my_row_ids.shift();
        $.ajax({
            cache    : false,
            url      : 'ajax2.php',
            data     : "workerID=" + next_id, // next ID here!
            dataType : 'json',
            success  : function(data) {
                           // do necessary things here...
                           // call your AJAX function again, with delay...
                           setTimeout(callAjax, my_delay);
                       }
        });
    }
}
Community
  • 1
  • 1
Chris Kempen
  • 9,491
  • 5
  • 40
  • 52
  • 2
    You know what? I like this better than my answer. +1 – cssyphus Sep 23 '13 at 18:06
  • Thank you @gibberish, I blame it on years of jQuery and JavaScript siege ;) – Chris Kempen Sep 23 '13 at 18:06
  • 1
    You know I was about to type "Wouldn't this recursion eventually get out of hand?" but then I started looking deeper into it and while there is a limit, it seems rather manageable: http://stackoverflow.com/a/7828803/16959 – Jason Sperske Sep 23 '13 at 18:09
  • 2
    Use this approach in the block COMPLETE is nice as well. – Thiago C. S Ventura Nov 28 '14 at 09:56
  • When doing this mine doesn't delay. The only thing I did different was not set a delay variable, but put it right in the setTimeout() adding a generic function inside of setTimeout made it work, but not nearly as tidy as this – garek007 Oct 12 '22 at 15:51
2

Note: Chris Kempen's answer (above) is better. Please use that one. He uses this technique inside the AJAX routine. See this answer for why using setTimeout is preferable over setInterval.


//Global var
is_expired = 0;

$(function (){

    var timer = setInterval(doAjax, 800);

    //At some point in future, you may wish to stop this repeating command, thus:
    if (is_expired > 0) {
        clearInterval(timer);
    }

}); //END document.ready

function doAjax() {
    $.ajax({                                      
        cache: false,
        url: 'ajax2.php',        
        data: "workerID=<?=$row['workerID'];?>",
        dataType: 'json',    
        success: function(data) {
            var id = data[0];              //get id
            var vname = data[1];           //get name
            //--------------------------------------------------------------------
            // 3) Update html content
            //--------------------------------------------------------------------
            $('#output').html("<b>id: </b>"+id+"<b> name: </b>"+vname);
        }
    }); //END ajax code block
} //END fn doAjax()
Community
  • 1
  • 1
cssyphus
  • 37,875
  • 18
  • 96
  • 111
0

I've devised a a wrapper method which adds a custom delay on-top of the default $.ajax method. This is a way to have (on all jQuery ajax calls) a delay, throughout your entire app.

Very handy in simulating real-life random latency.

(function(){
  $._ajaxDelayBk = $.ajax; // save reference to the "real" ajax method

 // override the method with a wrapper
  $.ajax = function(){
    var def = new $.Deferred(),
        delay = typeof $.ajax.delay == 'undefined' ? 500 : $.ajax.delay, 
        delayTimeout,
        args = arguments[0];

    // set simulated delay (random) duration
    delayTimeout = setTimeout(function(){
      $._ajaxDelayBk(args)
        .always(def.resolve)
        .done(def.resolve)
        .fail(def.reject)
    }, delay);

    def.abort = function(){
        clearTimeout(delayTimeout);
    };

    return def;
  }
})();

USE EXAMPLE:

// optional: set a random delay to all `ajax` calls (between 1s-5s)
$.ajax.delay = Math.floor(Math.random() * 5000) + 1000;

var myAjax = $.ajax({url:'http://whatever.com/API/1', timeout:5000})
  .done(function(){ console.log('done', arguments) })
  .fail(function(){ console.log('fail', arguments) })
  .always(function(){ console.log('always', arguments) })

// Can abort the ajax call
// myAjax.abort();
vsync
  • 118,978
  • 58
  • 307
  • 400
0
 var takeInput=true;
  $('#searchDrug').on('input',function() {
     if(!takeInput){return false;}
     takeInput=false;
     var timer = setTimeout(function() {
         $.ajax({
            type: 'POST',
            url: "{{route('AjaxSearchDrug')}}",
            data: {
               _token: '<?php echo csrf_token() ?>',
               'searchkeyword': searchkeyword,
            },
            success: function (data) {
                //do some logic then let keys be effective once more
                takeInput=true;
            }
        });
     }, 700); 
Omar
  • 607
  • 3
  • 8
  • 18