1

basically I want a Jquery function to call a PHP script multiple times, and every single time, load the response into a div, this is the code I have now:

images = 10;
while(images > 0)
    {
        $.ajax({        
            type: "POST",
            url: "processimage.php",
            data: { image : 1 },
            async: false,
            success: function(data) {   
                $( "#logger" ).append(data+ '<br />');
            }
        });
        images--;
    }

What this code is doing is processing all the images and then appending the full response, but I want it to append the response for every single image. Somehow the while block is entirely being processed before updating the #logger div. Am I missing something?

sigmaxf
  • 7,998
  • 15
  • 65
  • 125
  • 2
    until you remove async: false, this is impossible with your while loop. The browser will be locked up until the while loop is complete. – Kevin B Nov 01 '13 at 18:48
  • The while block actually runs before you get the response. ajax calls are async operations. jQuery will call your callback as soon as a response is available. – just lerning Nov 01 '13 at 18:50
  • Try wrapping the code inside the while loop in setTimeout with a delay of 0 ms, it may render each image one at a time. setTimeout causes the DOM the render before executing the next flow. See here for more detailed info: http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful – Rick Suggs Nov 01 '13 at 18:53

1 Answers1

2

you must remove the async: false. which in turn allows the requests to complete and be appended as they finish. However, you'll then realize that they are being appended out of order! to fix that, we can use promise objects and .then.

images = 10;

var req = $.ajax({
    type: "POST",
    url: "processimage.php",
    data: {
        image: images
    },
    success: function (data) {
        $("#logger").append(data + '<br />');
    }
});
images--;

while (images > 0) {
    req.then(function(){
        return $.ajax({
            type: "POST",
            url: "processimage.php",
            data: {
                image: 1
            },
            success: function (data) {
                $("#logger").append(data + '<br />');
            }
        });
    });
    images--;
}

Now, there's still one more possible issue. if you needed to pass the current value of images with each request, the previous code will send all requests after the first with the last value of images. To fix that, we can use an iffe.

images = 10;

var req = $.ajax({
    type: "POST",
    url: "processimage.php",
    data: {
        image: 1
    },
    success: function (data) {
        $("#logger").append(data + '<br />');
    }
});
images--;

while (images > 0) {
    (function(i){
        req.then(function(){
            return $.ajax({
                type: "POST",
                url: "processimage.php",
                data: {
                    image: i
                },
                success: function (data) {
                    $("#logger").append(data + '<br />');
                }
            });
        });
    })(images);
    images--;
}

And then you can make it DRYer as suggested below by storing the options in a separate variable:

images = 10;

var ajaxOpts = {
    type: "POST",
    url: "processimage.php",
    data: {
        image: 1
    },
    success: function (data) {
        $("#logger").append(data + '<br />');
    }
};

var req = $.ajax(ajaxOpts);
images--;

while (images > 0) {
    (function(i){
        req.then(function(){
            ajaxOpts.data.image = i;
            return $.ajax(ajaxOpts);
        });
    })(images);
    images--;
}
Kevin B
  • 94,570
  • 16
  • 163
  • 180