等待所有AJAX调用完成后显示对话框

9

我正在开发一个动态在线表单网站。在主表单中,我有多个子表单,可以动态地添加和删除。

<div class='subform'>
    //form fields 
    <input ...>
    ...
    <button class='subform_submit'>
</div>

对于每个子表单,我会在提交按钮上绑定一个AJAX调用,像这样:
$('#main').on('click', '.subform_submit', function(){
    // Get this subform's user input
    ...
    $.ajax({
        url: ..,
        type: ..,
        data: /* this subform's data */
    });
});

因此,在该页面中,根据用户的选择,我可能会有0到10个子表单。 此外,页面底部还有一个主提交按钮,可以将这些子表单和主表单的数据一起提交。

$('#main').on('click', '#submit', function(e){
    $('.subform_submit').click(); // Submit each subform
    bootbox.confirm({ });
})

一旦单击主提交按钮,我想显示一个加载图片,然后显示一个对话框(我在这里使用bootbox.confirm()),直到所有AJAX调用都完成。该对话框告诉用户整个表单(包括子表单)已被提交。但问题是,每个AJAX调用可能需要2秒钟才能完成,而且我不知道有多少个调用正在等待完成。如何编写此主提交按钮,以便它将:
  1. 立即显示加载图像,并
  2. 在所有AJAX调用完成后隐藏加载图像并显示对话框?

感谢 @Lewis 提供的最佳解决方案! - monknom
5个回答

4

跟踪子表单的数量;

$subFormsCount = $('.subform').length;

跟踪已提交的表单数量;

$submittedForms = 0;

每次表单提交完成后,将$submittedForms加一。
$.ajax({
  ..
  ..
  done: function(){
    $submittedForms++;
  }
})

创建一个全局计时器,以检查提交的表单数是否与子表单的总数相匹配。如果是,则隐藏对话框;
setInterval(function(){
  if($submittedForms == $subFormsCount){
   $('.dialog').show();
  }
}, 50ms)

编辑

您可以跳过全局计时器(因为这可能会有几毫秒的误差)- 在ajax.done中包含检查;

$.ajax({
  ..
  ..
  done: function(){
    $submittedForms++;

    if($submittedForms == $subFormsCount){
     $('.dialog').show();
    }
  }
})

在哪里应该放置对话框代码?如果在ajax.done中检查,如果没有子表单并且我仍然想看到对话框怎么办? - monknom
@monknom,我不确定你在问什么。我以为你想在子窗体提交时显示图像,而只有在它们完成后才显示对话框? - Lewis
抱歉我的英语不太好,这里讨论的是子表单提交时的图片和对话框。但是我想让人们知道整个表单已经被提交了,而不仅仅是子表单。 - monknom
以上的代码不适用于这种情况吗?$submittedForms和$subFormsCount都将等于0,因此匹配,应该显示对话框?我不确定我完全理解你的问题,也许其他人可以提供更多帮助。 - Lewis
@monknom 很高兴听到这个消息!祝你的项目好运。 - Lewis

2
你想要使用 .done() 来指定代码,在 AJAX 异步函数完成后才运行。
 $.ajax({
     url:..,
     type: ..,
     data: /* this subform's data*/ })
     .done(function() {
         //Put code here
     });

1

0

我假设你有9个子表单和1个主表单。 前8个子表单的代码将是相同的。

我在这里使用async:false:意味着下一个ajax调用将在第一个调用完成之前不会被调用。

示例代码格式:

var id = 5;
$.ajax({
    url:  ,
    type: 'POST',
    data: {'id':id},
    dataType: 'JSON',
    async: false,
    error : function(xhr, textStatus, errorThrown) {
        alert('An error occurred!');
    },
    success : function(response){

    }
});

只需在您的最后一个子表单(第9个子表单)中设置变量即可。

success : function(response){
        var counter = true;
    }

if(counter){
    /* Code to show dialog.*/
}

0
你可以使用$.when来等待每个请求完成。像这样的代码应该可以让你接近目标。你基本上需要将所有的ajax请求存储在一个数组中,并将其作为参数传递给when
$('#main').on('click', '.subform_submit', function () {

  var formRequests = $('.subform').map(function () {
    var $form = $(this);
    return $.ajax({
      url: '',
      data: $form.serialzeArray()
    });
  }).get();

  $.when.apply(undefined, formRequests).done(function () {
    console.log('All done!');
  });

});

这里有一个我刚刚编写的非常相似的小演示:https://jsfiddle.net/g9a06y4t/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接