-->

Wait for AJAX Call (POST) to Finish

2020-08-22 05:03发布

问题:

I am using the jQuery UI tabs where each tab has a different form on it. After the user enters various pieces of data, they submit the entire set of tabs so that each tab posts to the server asynchronously. This works well, and I have no problems here.

However, where I run into a problem is that, the last form that I post has to happen AFTER all the other posts complete. General idea is like this:

postForm(0, "#Form1");
postForm(1, "#Form2");
postForm(2, "#Form3");
postForm(3, "#Form4");
$.post('Project/SaveProject', function (data) {
    $('<div class="save-alert">The current project has been saved.</div>')
    .insertAfter($('#tabs'))
    .fadeIn('slow')
    .animate({ opacity: 1.0 }, 3000)
    .fadeOut('slow', function () {
        $(this).remove();
    });
});

The postForm function does a little bit of processing and then makes an AJAX $.post call. The last $.post performed here (to 'Project/SaveProject') must wait until those other posts are completed. What is the best way to go about doing that?

回答1:

You can just use the .ajaxStop() event that fires when all the other AJAX POSTs finish, assuming you're doing no other AJAX work then, like this:

postForm(0, "#Form1");
postForm(1, "#Form2");
postForm(2, "#Form3");
postForm(3, "#Form4");
$(document).ajaxStop(function() {
  $.post('Project/SaveProject', function (data) {
    $('<div class="save-alert">The current project has been saved.</div>')
    .insertAfter($('#tabs'))
    .fadeIn('slow')
    .animate({ opacity: 1.0 }, 3000)
    .fadeOut('slow', function () {
      $(this).remove();
    });
  });
  $(this).unbind('ajaxStop');
});

.ajaxStop() fires when all AJAX requests that are running complete, so it'll only fires when all of those POSTs have returned, jQuery keeps a count internally ($.active, $.ajax.active in jQuery 1.5) to determind how many simultaneous AJAX requests are outstanding...when it gets back to 0 this event fires.

This approach lets you do the other form submissions simultaneously, and do the final form ASAP after.



回答2:

You could always make all the posts synchronous using something like


$.ajax({
   type: "POST",     
   async: false,
   url: "",
   ...

of course it wouldnt be as fast but it does solve your problem if $(document).ajaxStop is not an option



回答3:

Callbacks:

Define postForm to take a callback:

function postForm(ind, id, callback)
{
  // ...
  $.post(url, function()
  {
    // ...
    callback();
  });
}

Then do something like the below. You can use recursion to write it in a less hard-coded way, which might be particularly useful if there are more forms.

postForm(0, "#Form1", function()
{
    postForm(1, "#Form2", function()
    { 
        postForm(2, "#Form3", function()
        {
            postForm(3, "#Form4", function()
            {
                $.post('Project/SaveProject', function (data) {
                    $('<div class="save-alert">The current project has been saved.</div>')
                        .insertAfter($('#tabs'))
                        .fadeIn('slow')
                        .animate({ opacity: 1.0 }, 3000)
                        .fadeOut('slow', function () {
                            $(this).remove();
                        });
                });
            });
        });
    });
});


回答4:

The problem with ajaxStop is that it will fire every time any ajax is done. An alternative is implementing your own method stack like this:

var stack = []
postForm(var1, var2){
    stack.push(1);
    //Do postForm stuff
    stack.pop();
    if (stack == undefined){
        //Call the last post method
    }
}
postForm(0, "#Form1");
postForm(1, "#Form2");
postForm(2, "#Form3");
postForm(3, "#Form4");
$.post('Project/SaveProject', function (data) {
    $('<div class="save-alert">The current project has been saved.</div>')
    .insertAfter($('#tabs'))
    .fadeIn('slow')
    .animate({ opacity: 1.0 }, 3000)
    .fadeOut('slow', function () {
        $(this).remove();
    });
});


标签: jquery ajax post