I have problem to make delays between ajax requests in loop. I want script to wait 7 seconds to do next one. Requests are not identical, and I don't know how many of them can be.
$(document).ready(function () {
var announce = $("#announce").data('id');
var lots_cnt = parseInt($("#announce").data('lotscnt'));
for (var i = 0; i < Math.ceil(lots_cnt/20); i++) {
$.ajax({
method: "GET",
url: "/project/lots/"+announce+"/"+(i+1),
async: false,
beforeSend: function () {
$("#console").append("<strong>Parsing lots from page "+(i+1)+"...</strong><br/>");
},
complete:function(){
},
success: function (m) {
$("#console").append(m);
addprogressstep();
setTimeout(function() { $("#console").append("Waiting 7 sec ...<br/>"); }, 7000);
},
error:function(jqXHR, textStatus, errorThrown){
}
});
};
});
This is a fantastic question!
I see you're using jQuery .ajax. According to jQuery documentation, $.get()
now returns a promise. We can use promises to acheive what you want.
Firstly, in your for loop, for (var i = 0; i < Math.ceil(lots_cnt/20); i++) {
, the first thing you do is run $.ajax
. Instead of that, what we're going to do is build an array of functions, where each function returns a promise.
var funcArray = [];
// EDIT changed var i to let i
for (let i = 0; i < Math.ceil(lots_cnt/20); i++) {
var getFunction = function(){
var getPromise = $.get(...);
return getPromise;
}
funcArray.push(getFunction);
}
Then, you're going to write a recursive(ish) function to process each function, when the previous one finishes (and after a timeout if you like)
function runNext(){
if (funcArray.length > 0) {
var nextFunction = funcArray.shift();
nextFunction() // this is our $.get promise
.then(function(resultOfGet){
// do something with your result
setTimeout(runNext,1000*7);
})
}
}
runNext();
--- edit --- Here's how you might turn $.ajax
into a promise:
function ajx(i) {
return new Promise(function(resolve, reject){
$.ajax({
method: "GET",
url: "/project/lots/"+announce+"/"+(i+1),
async: false,
beforeSend: function () {
$("#console").append("<strong>Parsing lots from page "+(i+1)+"...</strong><br/>");
},
complete:function(){
},
success: function (m) {
$("#console").append(m);
addprogressstep();
resolve(m);
},
error:function(jqXHR, textStatus, errorThrown){
reject(jqXHR, textStatus, errorThrown);
}
});
})
}
you can fix with map
instead of for
.
if use map, you can change async setting true
When dealing with asynchronous processing, it is better to use map rather than the for statement.