Set a delay in a repeating jQuery / Ajax function - javascript

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?

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);
}
});
}
}

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()

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();

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);

Related

Insert data into MySQL Databse with PHP/AJAX, execute success option AFTER it's inserted (Callback)

I've been trying to make a simple site, and I can't quite wrap my head around some of the things said here, some of which are also unrelated to my situation.
The site has a form with 3 input boxes, a button, and a list. The info is submitted through a separate PHP file to a MySQL database, once the submit button is clicked. I'm supposed to make the list (it's inside a div) update once the info is successfully sent and updated in the database. So far I've made it work with async:false but I'm not supposed to, because of society.
Without this (bad) option, the list doesn't load after submitting the info, because (I assume) the method is executed past it, since it doesn't wait for it to finish.
What do I exactly have to do in "success:" to make it work? (Or, I've read something about .done() within the $.ajax clause, but I'm not sure how to make it work.)
What's the callback supposed to be like? I've never done it before and I can get really disoriented with the results here because each case is slightly different.
function save() {
var name = document.getElementById('name');
var email = document.getElementById('email');
var telephone = document.getElementById('telephone');
$.ajax({
url: "save.php",
method: "POST",
data: { name: name.value, email: email.value, telephone: telephone.value },
success: $("List").load(" List")
});
}
Thank you in advanced and if I need include further info don't hesitate to ask.
From this comment
as far as i know the success function will be called on success you should use complete, A function to be called when the request finishes (after success and error callbacks are executed). isnt that what you want ? – Muhammad Omer Aslam
I managed to solve the issue simply moving the $.load clause from the success: option to a complete: option. (I think they're called options)
I haven't managed error handling yet, even inside my head but at least it works as it should if everything is entered properly.
Thanks!
(Won't let me mark as answered until 2 days)
I would first create an AJAX call inside a function which runs when the page loads to populate the list.
window.onload = populatelist();
function populatelist() {
$.ajax({
type: "POST",
url: "list.php",
data: {function: 'populate'},
success: function(data) { $("#list").html("data"); }
});
}
Note: #list refers to <div id="list> and your list should be inside this.
I would then have another AJAX call inside a different function which updates the database when the form is submitted. Upon success, it will run the populatelist function.
function save() {
var name = document.getElementById('name');
var email = document.getElementById('email');
var telephone = document.getElementById('telephone');
$.ajax({
type: "POST",
url: "list.php",
data: {function: 'update', name: name.value, email: email.value, telephone: telephone.value },
success: function() { populatelist(); }
});
}
list.php should look like this:
<?php
if($_POST['function'] == "populate") {
// your code to get the content from the database and put it in a list
}
if($_POST['function'] == "update") {
// your code to update the database
}
?>
I will show you piece of solution that I use in my project. I cannot say it is optimal or best practices, but it works for me and can work for you:
PHP:
function doLoadMails(){
//initialize empty variable
$mails;
$conn = new mysqli($_POST['ip'], $_POST['login'], $_POST['pass'], $_POST['db']);
// Check connection
if ($conn->connect_error) {
die("");
}
//some select, insert, whatever
$sql = "SELECT ... ... ... ";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row, j is counter for rows
$j =0;
while($row_a = $result->fetch_assoc()) {
//for each row, fill array
$mails[$j][0] = $row_a["name"] ;
$mails[$j][1] = $row_a["mail"] ;
$mails[$j][2] = $row_a["language"] ;
$j++;
}
}
//if $mails has results (we added something into it)
if(isset($mails)){
echo json_encode($mails);/return json*/ }
else{
//some error message you can handle in JS
echo"[null]";}
}
and then in JS
function doLoadMails() {
$.ajax({
data: { /*pass parameters*/ },
type: "post",
url: "dataFunnel.php",
success: function(data) { /*data is a dummy variable for everything your PHP echoes/returns*/
console.log(data); //you can check what you get
if (data != "[null]") { /*some error handling ..., in my case if it matches what I have declared as error state in PHP - !(isset($mails))*/ }
}
});
Keep in mind, that you can echo/return directly the result of your SQL request and put it into JS in some more raw format, and handle further processing here.
In your solution, you will probably need to echo the return code of the INSERT request.

More than 1 ajax function being called at once, PHP, AJAX

I have a working ajax function that when called will display the current time, and then setTimeout for ten seconds before displaying the new time. I call this function when onkeyup is triggered on an text input, and it works. But there is a slight problem. If I type something else in the text input after the ajax function has already been called, it'll call another ajax function, and have two ajax functions running at the same time. For example:
If the first ajax function was called at 3:00:00 when it was triggered, and the second ajax function is called at 3:00:05, that means that there are now two ajax functions running at the same time. The first ajax function will be triggered again at 3:00:10, after the 10 second setTimeout, and the second ajax function will be triggered again at 3:00:15, after its 10 second setTimeout. So the more times you trigger the onkeyup in the text input, the more times the function will be called. I just want 1 function of itself to be running at the same time, not 2, 3, or more. How do I do that? Thanks.
ajax.php
<script type = "text/javascript">
function timeoutAjax(url,type,theName,id,timeout) {
$.ajax({
type: "POST",
url: url,
data: { select: $(type+'[name='+theName+']').val()},
error: function(xhr,status,error){alert(error);},
success:function(data) {
document.getElementById( id ).innerHTML = data;
setTimeout(function() { timeoutAjax(url,type,theName,id,timeout); }, timeout);
}
});
}
</script>
test1.php
<?php
include('ajax.php');
echo "<input type = 'text' name = 'name' onkeyup = 'timeoutAjax(\"test2.php\",\"input\",\"name\",\"output1\",\"10000\")'>";
echo "<div id = 'output1'/>";
?>
test2.php
<?php
$time = date('H:i:s A');
echo $time;
?>
************MORE DETAILS************
echo "<input type = 'submit' name = 'name1' value = 'Reset' onclick = 'timeoutAjax(\"test2.php\",\"input\",\"name1\",\"output1\",\"10000\")'>";
echo "<input type = 'submit' name = 'name2' value = 'Reset' onclick = 'timeoutAjax(\"test2.php\",\"input\",\"name2\",\"output2\",\"10000\")'>";
echo "<div id = 'output1'/>";
echo "<div id = 'output2'/>";
If I understand your question correctly, you actually trying to achieve two things here:
1. Only the last ajax call
After the last key stroke, do some ajax call. Any ajax call that is already busy can be skipped, you are just interested in the last one.
This should not be to hard. jQuery returns an xhr object when you call the ajax function. On that xhr object, you can just call the abort() method to cancel a pending call. (Abort Ajax requests using jQuery)
2. Repeat the ajax call every x time
Right now you set a timeout in your ajax success function that will just repeat the call after a given time. Problem is that when you call your ajax function again from the outside (so not recursively I mean, but by another keystroke or something) you will just create another infinite string of ajax calls. After a while you'll end up with a huge queue of calls that will start to overlap and eat up all your resources.
This can easily be solved by storing the result of that setTimeout in a variable, and calling clearTimeout on that variable each time before you set a new timeout. This way you cancel the old 'queue' and just start a new one.
So enough poor english, let's try to show what I mean by updating your code:
function timeoutAjax(url, type, theName, id, timeout, trigger) {
// abort pending calls
if (trigger.xhr) {
trigger.xhr.abort();
}
// abort queued calls
clearTimeout(trigger.queued);
// make the call
trigger.xhr = $.ajax({
type: "POST",
url: url,
data: {
select: $(type + '[name=' + theName + ']').val()
},
error: function (xhr, status, error) {
alert(error);
},
success: function (data) {
document.getElementById(id).innerHTML = data;
// queue a new call
trigger.queued = setTimeout(function () {
timeoutAjax(url, type, theName, id, timeout, trigger);
}, timeout);
}
});
}
Just one more sidenote. Even with the changes I made to your code, you will be aborting and making a new ajax call on every key stroke. And aborting an ajax call does not automatically mean your server stops handling the request, depnding on what backend you are using. For the simple php script you are using now it is probably fine, but still, it is probably better to wait until the user is done with typing before you make your first call. This is called Debouncing and isn't very hard to implement either: http://davidwalsh.name/javascript-debounce-function
Create a status variable that tracks if the ajax call is running. Set it to false initially. Then when the function is called, check the status; if not running execute the ajax call, set the status var to true, then set it to false again in the success callback:
<script type = "text/javascript">
//Create the status var (This may not be the best place to initialize it). Use your best judgement.
var running = false;
function timeoutAjax(url,type,theName,id,timeout) {
//Check if there is an ajax call in progress. If not execute one.
if(!running)
{
//Change the status to running
running = true;
console.log('In if')
console.log(running)
$.ajax({
type: "POST",
url: url,
data: { select: $(type+'[name='+theName+']').val()},
error: function(xhr,status,error){alert(error);},
success:function(data) {
document.getElementById( id ).innerHTML = data;
setTimeout(function() {
//Set the status to false for the inner function call
running = false;
timeoutAjax(url,type,theName,id,timeout);
//Set the status to true for the outer function call
runnng = true;
}, timeout);
}
});
}
}
</script>
The outer function which triggers the first ajax call and the timeout will only be run once,; however, the inner function will run every ten seconds continuously.
I hope this works for you, If so, please accept this answer. Thanks

how to refresh dynamically generated divs using ajax?

I am generating dynamic divs and need to refresh them every 10 seconds.
Earlier I used meta refresh but didn't like the flickering of page.
I have tried to insert the ajax code but got failed.
below is my code without ajax,please tell me how and where to insert the ajax refresh code.
$(document).ready(function (){
var n = 9;
for(var i=0; i<n; i++){
var div = document.createElement('div');
div.className = "d5";
div.id=i+1;
// alert(div.id);
document.getElementById('container').appendChild(div);
$.ajax({
async : false,
url : 'myapi.php', //the script to call to get data
data : "", //you can insert url argumnets here to pass to api.php for example "id=5&parent=6"
dataType : 'json', //data format
success : function(data){ //on recieve of reply
var Name = data[2];
var subdomain = data[15];
var uniqueid = data[1];
var shop_photo = data[3];
var offer = data[19]; //get id
//var vname = data[1]; //get name
//$('#'+div.id).html("<a href='http://www."+subdomain+".shoppinonline.com'>"+Name+"</a>");
//$('#'+div.id).html("<img class='shopperspic' src='b2b/shop_image/"+uniqueid+"/"+shop_photo+"' alt='' /><a href='http://www."+subdomain+".shoppinonline.com'>"+Name+"</a><br>Special Offer<br><p>"+offer+"</p>");
if(offer == ""){
$('#'+div.id).html("<div class='div1'><img class='shopperspic' src='b2b/shop_image/"+uniqueid+"/"+shop_photo+"' alt='' /></div><div class='div2'><a href='http://www."+subdomain+".shoppinonline.com'>"+Name+"</a></div></div>");
}else{
$('#'+div.id).html("<div class='div1'><img class='shopperspic' src='b2b/shop_image/"+uniqueid+"/"+shop_photo+"' alt='' /></div><div class='div2'><a href='http://www."+subdomain+".shoppinonline.com'>"+Name+"</a></div><div class='div3'>Special Offer<br class='br_special'>"+offer+"</div></div>");
}
}
});
}
});
First, enclose your existing code(loop and the ajax call) in a function. You can then create a setTimeOut loop using recursion and get your function called every 10 seconds .
$(document).ready(function(){
timeout();
function timeout() {
setTimeout(function () {
//Call the function that makes the ajax request
//This code will re-execute after every 10 seconds
timeout();
}, 10000);
}
});
Also, doing async: false, you are actually abusing the very nature of ajax calls. It will block your script until the request has been fulfilled.
Cheers!
Set A timer Of Ten Second And Call Ajax Method Inside That I think This Will Solve Your Problem

MySQL / AJAX / jQuery Autocomplete

I am attempting to make a search bar on the top of my website which will search through a table with relatively low stringency. Basically, the user types a key word corresponding to one of the three columns below and they will send an AJAX request and a link to the corresponding page will pop up in my div.
For some reason, no matter what I try, I can't get the "5gooper" entry to show up. When I search "a" or "aa", the other two show up but no combination of letters will return the 5gooper entry. Here is my code:
PHP
$searchquery = $_POST['searchquery'];
$searchquery2 = "%$searchquery%";
$query = "SELECT * FROM data WHERE
name LIKE '$searchquery2'
OR author LIKE '$searchquery2'
OR project LIKE '$searchquery2'
OR protocol LIKE '$searchquery2'
ORDER BY DATE DESC LIMIT 20";
AJAX
$('#sbar').keyup(function(){
var query = $(this).val();
$.ajax
({
url: "autocomplete.php",
data: {searchquery: query},
type: 'POST',
success: function(data){
$('#acd').html(data); //acd stands for auto complete div
}
});
});
Any idea as to why the search isn't entirely working? Even with flanking '%'s, it won't find the gooper entry, no matter what I type.
Thanks
This is how I would do it:
$('#search-input input[type=text]').on('keyup', function(){
var input = $('#search-input input[type=text]').val();
var $name = $.trim(input);
if($name.length > 3 && $name.length < 25) {
delay(function() {
var url = encodeURI("search/" + $name);
$.ajax({
url: url,
type: "get",
dataType: 'json',
success: function(data) {
console.log(data);
}
});
}, 500);
}
});
and my delay function
var delay = (function() {
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
This is for GET and can easily be changed to POST. It's equipped with spam protection by executing the ajax call every 500 ms and the character range can be adjusted to work after x characters but no more than x characters.

Rewrite ajax request and the values returned

I need help to write this without the async: false,.
var imageX;
var groupX;
$.ajax({
type:'GET',
url:'php/myphp.php',
dataType:'json',
async: false,
success: function(response){
imageX = response[0].studentName,
groupX = response[0].subjectId;
alertImageX();
}
});
function alertImageX() {
(function() {
var image = {
'back': { 'url':imageX, 'img':null },
'front': { 'url':'img/bg.jpg', 'img':null }
};
php
$query = $db->prepare('SELECT studentName, subjectId FROM grade3 WHERE eligible = ? LIMIT 1');
$array = array('Yes');
$query->execute($array);
$result = $query->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
"async: false" should not be needed in this situation because your response is already processed after AJAX request is complete, as it is placed inside the "success" element. Sorry if I missed any detail
EDIT:
Sorry I just read your comment regarding what you want to achieve. The response variable contains whatever the script called by AJAX echoed (in case of a PHP script), so you basically need to echo what you want the script to return and access that through the response variable.

Categories

Resources