在每个循环中执行ajax调用

时间:2014-01-10 10:25:07

标签: javascript jquery ajax

我有一个网页,我在这个页面上有5个复选框。使用while循环我正在浏览所有选中的复选框,并在选中时执行AJAX调用。

问题是复选框的顺序很重要。或者至少第一个AJAX调用必须在其他AJAX调用完成之前执行一些特殊操作。然而,似乎所有AJAX调用都以正确的顺序完成,后面的PHP代码没有以相同的顺序执行,这导致第一个AJAX调用例如被执行为第三个。

我怎样才能做到这一点?在我的代码下面。

$("#submitforms").click(function(){
    var btn = $(this);
    var first = "true";
    var formsSend = 0;
    var formsToSend = $(":checkbox:checked").length
    var ids = "";
    console.log("To send: "+formsToSend);
    $('span.postable').each(function(index){
      console.log(index);
      add = $(this).find('[name="cc"]').is(':checked');
      if(add){
        btn.css("background-image", "url(/images/wait.gif)");
        btn.html("You will be redirected in a second!");
        sku = $(this).find('.sku').val();
        price = $(this).find('.price').val();
        XID = $(this).find('[name="XID"]').val(); 
        $.ajax({                            
          type: "POST",
          url: "/addtocart",   
          data: {sku:sku, qty:"1", price:price, XID:XID, first:first}   
        }).done(function(data) {
          formsSend++;
          console.log("Forms send: "+formsSend + " > "+index);
          if(formsSend >= formsToSend){
            // redirect to cart here after all forms have been posted
            console.log("forward");
            window.location.href = '/cart';

          }
        });
        first = "false";
      }
    });

在控制台中显示以下内容。

To send: 5
0 
1 
2 
3 
4 
Forms send: 1 > 4 
Forms send: 2 > 0 
Forms send: 3 > 2 
Forms send: 4 > 1 
Forms send: 5 > 3 
forward 

如您所见,它发送索引为0的表单1,因此第一个 然后它发送表单2,索引4,然后表单3,索引2,等等。

因此,表格“完成”的顺序与它们的应用方式不同> 4,0,2,1,3代替0,1,2,3,4。订单每次都不同。

使用参数first我希望tel脚本/addtocart,它是第一个排队的,所以它应该做一些特别的事情。但不幸的是,第一次并不总是第一次。

顺便说一句:

顺序并不那么重要,唯一重要的是在脚本/addtocart中我必须知道它是第一个。

2 个答案:

答案 0 :(得分:2)

每个ajax函数都会返回一个使用它的promise对象。 promises将包含所有ajax承诺,$.when将解析所有ajax调用并触发回调done;

试试这个

$("#submitforms").click(function(){
    var btn = $(this);
    var first = "true";
    var formsSend = 0;
    var formsToSend = $(":checkbox:checked").length
    var ids = "";
    var promises = new Array(); // creating the array for promise.
    console.log("To send: "+formsToSend);
    $('span.postable').each(function(index){
      console.log(index);
      add = $(this).find('[name="cc"]').is(':checked');
      if(add){
        btn.css("background-image", "url(/images/wait.gif)");
        btn.html("You will be redirected in a second!");
        sku = $(this).find('.sku').val();
        price = $(this).find('.price').val();
        XID = $(this).find('[name="XID"]').val(); 
        var promise = $.ajax({                            
          type: "POST",
          url: "/addtocart",   
          data: {sku:sku, qty:"1", price:price, XID:XID, first:first}   
        })
       promises.push(promise);// pushing the promise to the array
      }
    });

    $.when.apply($, promises).done(function(){
          window.location.href = '/cart';
    });

});

答案 1 :(得分:1)

如果重构循环以便只是收集数组中Ajax调用所需的数据,则可以使用递归函数来按顺序处理Ajax调用 。这样做的好处是它会发生异步,因此不会阻止任何其他处理。

这是一个快速破解这个概念和你的代码......

$("#submitforms").click(function () {
    var btn = $(this);
    var first = "true";
    var formsSend = 0;
    var formsToSend = $(":checkbox:checked").length
    var ids = "";
    console.log("To send: " + formsToSend);
    var queue = [];
    $('span.postable').each(function (index) {
        console.log(index);
        add = $(this).find('[name="cc"]').is(':checked');
        if (add) {
            btn.css("background-image", "url(/images/wait.gif)");
            btn.html("You will be redirected in a second!");
            sku = $(this).find('.sku').val();
            price = $(this).find('.price').val();
            XID = $(this).find('[name="XID"]').val();
            queue.push({
                sku: sku,
                qty: "1",
                price: price,
                XID: XID,
                first: first
            });
        }
    });
    // Now process the queue of data and do processing once all request are completed
    ProcessQueue(queue, function () {
        formsSend++;
        console.log("Forms send: " + formsSend + " > " + index);
        if (formsSend >= formsToSend) {
            // redirect to cart here after all forms have been posted
            console.log("forward");
            window.location.href = '/cart';
        });
    });
});

// Recusively process the Ajax calls (actually this is just chained Async)
function ProcessQueue(queue, callback) {
    if (queue.length) {
        $.ajax({
            type: "POST",
            url: "/addtocart",
            data: queue[0]
        }).done(function (data) {
            ProcessQueue(queue.slice(1), callback);
        });
    } else {
        callback();
    }
}

不考虑您的计数器等道歉,但这应该指向正确的方向(并且是一种通常有用的技术)。

虽然使用promises是一个很好的选择,但如果你尝试运行大量并行的ajax负载,它就会成为瓶颈(特别是在移动设备上)。我常常使用这种技术回退到顺序异步。