1

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

                }
            });
    };

});
5
  • setTimeout(). That said, sending that many AJAX requests isn't a great idea if it can be avoided. I'd suggest looking in to sending all data in a single request, if possible. However, you should definitely remove async: false as it's horrendous practice - if you check the console you'll even see the browser telling you not to use it. Commented Oct 3, 2017 at 8:58
  • Its not that many requests as it looks like, its between 1 to 6, so I think browsers and network are good with that. Unfortunately, I can't make one request instead of this loop, and I need this delay to avoid "429 Too Many Requests" error. Commented Oct 3, 2017 at 9:08
  • Browsers are fine with it, however your server/hosting company may not be if you have a N users * N requests per minute being sent to the server. Commented Oct 3, 2017 at 9:10
  • @ГлебГарипов if you need help implementing my answer, let me know Commented Oct 3, 2017 at 9:44
  • @TKoL Thank you for your offer of help, it's highly appreciated. You gave me an idea how to solve my problem. I'll describe my solution below your answer. Commented Oct 3, 2017 at 10:51

2 Answers 2

1

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);
            }
        });
    })    
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I didn't thought about recursion. Your code didn't worked for me, it was trying to execute function from funcArray with i=6 all the time. So I did it that way: var lots_cnt = parseInt($("#announce").data('lotscnt')); var pages = Math.ceil(lots_cnt/20); var currentPage=1; function runNext(){ $.get("/goszakup/lots/"+announce+"/"+currentPage,function(m){ $("#console").append(m); addprogressstep(); currentPage++; if(currentPage<=pages) setTimeout(runNext,1000*7); }); } runNext();
Ah yes, when you loop that way with clojures the variable 'i' would end up always with the biggest value. I didn't think about that.
@ГлебГарипов that bug on the 'i' loop could be fixed by let instead of var i think.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.