MrPHP
MrPHP

Reputation: 972

Dynamically chain jQuery $.post() and fire call event after all are complete.

I have a series of elements that I want to grab, loop, validate, save and continue to the next element, once all elements 'saves' are complete, then redirect the user.

The number of elements is dynamic, and genrally saves are fast.

$.each($('#wrapper').find('.question'), function(i, question) {
    var post_data = false;
    if(question) { 
        // validate based on type of question/expected data etc.... 
        // example data object
        post_data = {
            'question_id': question_id, 
            'question_text': question_text,
            // etc.... 
        };
        if(post_data) { 
            $.post('ajax_save_question', post_data)
            .done(function(data) { question.addClass('saved'); });
        }
    } else {
        // exit loop altogether
    }
}); 

// run after loop has finished and all questions have been saved.. 
window.location = 'display_results'; 

Upvotes: 1

Views: 421

Answers (3)

guest271314
guest271314

Reputation: 1

$(function() {
var arr = $.makeArray($("#wrapper").find(".question"));
$.when(arr)
.then(function(elem) {
  $.each(elem, function(index, value) {
      var post_data = {
          "question_id" : $(value).attr("id"),
          "question_text" :  $(value).text()
      };
      if (post_data) {
          var settings = function (_post_data) {
            return {
              url: "/echo/json/",
              type: "POST",
              async: true,
              data: {
                    json: JSON.stringify(_post_data)
                  }
              }
          };
          $.ajax(settings(post_data))
          .done(function(data, textStatus, jqxhr) {
            console.log(data);
            $(value).addClass("saved");              
          })          
      }
      else { 
        return false
      }
  });
    return [ elem, $(document) ]
})
.always(function(data) {
    data[1].on("ajaxStop", function(e) {
        $("body").append(data[0].length 
        + " items completed, done at " + $.now());
        // `complete` `callback`, i.e.g., 
        // run after loop has finished and all questions have been saved..  
        // window.location = "display_results";
    });
});
});

jsfiddle http://jsfiddle.net/guest271314/GGhq5/

Upvotes: 0

PeterKA
PeterKA

Reputation: 24638

You may also want to look at $.ajaxStop event. It listens for when the last in a series of ajax requests completes:

$(function() {
    $( document ).ajaxStop( function() {
        //all done -- you can now redirect to the next page
    });
});

Your existing code remains unchanged.

Upvotes: 0

Luke
Luke

Reputation: 8407

You can use $.when, where you can pass in as many deferreds as you like. when all are done, you will be notified through the callback attached through .then() . See Documentation

var myFirstPost = $.post( ... ); 
var mySecondPost = $.post( ... );

$.when(myFirstPost, mySecondPost).then(function() {
    alert("all done");
});

In your case, where your $.post is quite deep in another function call, you should save all your post calls into some array. As $.post always returns a Promise Object, you can just put it into an array. After you have ran all your loop, use the $.when

// use apply, to pass in an array of promises
$.when.apply($, allMyPromisesArray).then( ... )

Upvotes: 1

Related Questions