Paul
Paul

Reputation: 11756

How do I wait for multiple jquery posts to complete?

I'm trying to clear a busy icon and re-enable my delete button once the multiple jquery posts have completed. Here is my current code:

    $('#deleteimgs').live('click', function(e) {
        e.preventDefault();

        if ($('input[name="chk[]"]:checked').length > 0 ) {

            $('#deleteimgs').button('loading');
            $('#saveicon').show();

            var boxes = $('input[name="chk[]"]:checked');
            $(boxes).each(function(){

                 var id = $(this).attr('id').substr(7);
                 var self = this;

                 $.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
                    if (data.success) {
                        $(self).hide();
                        $("#img_"+id).hide(250);
                    }
                }, "json");
            });

            $('#saveicon').hide();
            $('#deleteimgs').button('reset');
        }

    });

My hide call and reset call are being trigger prior to completion of the foreach loop. Is there a way to wait for completion before making these two calls?

$('#saveicon').hide();
$('#deleteimgs').button('reset');

Upvotes: 0

Views: 362

Answers (4)

Patrick Roberts
Patrick Roberts

Reputation: 51916

To follow up on DwB's answer, using async would be an easy way to supply the intermediary function. instead of:

$(boxes).each(function(){

Use:

async.parallel(boxes.toArray().map(function(elem){
    var self = elem;
    return function (callback) {
        var id = $(self).attr('id').substr(7);

        $.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
            if (data.success) {
                $(self).hide();
                $("#img_"+id).hide(250);
                callback();
            } else {
                callback(new Error("request failed"));
            }
        }, "json");
    }
}), function (err) {
    if(err) {
        console.log(err);
    } else {
        $('#saveicon').hide();
        $('#deleteimgs').button('reset');
    }
});

That should work.

Upvotes: 0

adeneo
adeneo

Reputation: 318282

Try something like :

$(document).on('click', '#deleteimgs', function(e) {
    e.preventDefault();

    if ($('input[name="chk[]"]:checked').length > 0 ) {

        $('#deleteimgs').button('loading');
        $('#saveicon').show();

        var boxes = $('input[name="chk[]"]:checked'),
            xhr = [];
        boxes.each(function(){
             var self = this,
                 id = self.id.substr(7);

             var request = $.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
                if (data.success) {
                    $(self).hide();
                    $("#img_"+id).hide(250);
                }
            }, "json");
            xhr.push(request);
        });

        $.when.apply(null, xhr).done(function() {
            $('#saveicon').hide();
            $('#deleteimgs').button('reset');
        });
    }
});​

This will store all the requests in an array that is later passed to $.when, and when they are all done the done() function will be executed.

Upvotes: 1

DwB
DwB

Reputation: 38310

You need to count the number of posts you make, call an intermediary function to count the replys, then do the hide and reset after all calls have completed.

for example:

var postCount = 0;

function allPostsDone()
{
   $('#saveicon').hide();
   $('#deleteimgs').button('reset');
}

postCount += 1;
$.post("/functions/photo_functions.php",
       { f: 'del', imgid: id},
       function(data)
       {
         if (data.success)
         {
           $(self).hide();
           $("#img_"+id).hide(250);
         }

         postCount -= 1;
         if (postCount == 0)
         {
           allPostsDone();
         }
       }, "json");

Upvotes: 0

Justin Helgerson
Justin Helgerson

Reputation: 25541

You should use the success callback method to complete any tasks once the HTTP request has finished. Inside of the callback you should keep track of how many requests have completed, and when your last request has finished, then execute the code of your desire.

You could restructure this code in a few ways, but, it should give you a general idea of how to handle the situation.

var boxes = $('input[name="chk[]"]:checked');
var totalBoxes = boxes.length;
var completedRequests = 0;

$(boxes).each(function(){

     var id = $(this).attr('id').substr(7);
     var self = this;

     $.post("/functions/photo_functions.php", { f: 'del', imgid: id}, function(data){
        if (data.success) {
            $(self).hide();
            $("#img_"+id).hide(250);

            //Increment the complete request count.
            completedRequests++;

            //Check if the last request has finished.  If it has, do your stuff!
            if (completedRequests == totalBoxes) {
                $('#saveicon').hide();
                $('#deleteimgs').button('reset');
            }
        }
    }, "json");
});

Upvotes: 3

Related Questions