Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在each循环中执行ajax调用_Javascript_Jquery_Ajax - Fatal编程技术网

Javascript 在each循环中执行ajax调用

Javascript 在each循环中执行ajax调用,javascript,jquery,ajax,Javascript,Jquery,Ajax,我有一个网页,我在这个网页上有5个复选框。使用whileloop,我正在运行所有选中的复选框,并在选中时执行AJAX调用 问题是复选框的顺序很重要。或者至少第一个AJAX调用必须先执行一些特殊的操作,然后才能执行另一个AJAX调用。然而,似乎所有的AJAX调用都是按正确的顺序执行的,后面的PHP代码不是按相同的顺序执行的,这导致第一个AJAX调用作为第三个调用执行 我怎样才能做到这一点?下面是我的代码 $("#submitforms").click(function(){ var btn

我有一个网页,我在这个网页上有5个复选框。使用whileloop,我正在运行所有选中的复选框,并在选中时执行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,因此 然后它发送带有索引4的表单2,然后发送带有索引2的表单3,以此类推

因此,表单“完成”的顺序与它们应该是>4,0,2,1,3而不是0,1,2,3,4的顺序不同。每次的顺序都不一样

使用参数
first
我想告诉脚本
/addtocart
它是行中的第一个,所以它应该做一些特殊的事情。但不幸的是,第一次并不总是第一次

顺便说一句:


顺序并不那么重要,唯一重要的是在脚本
/addtocart
中,我必须知道它是第一个。每个ajax函数都将返回一个promise对象,利用它<代码>承诺将包含所有ajax承诺和$。当解决所有ajax调用并启动回调完成

试试这个

$("#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';
    });

});

如果重新构造循环,使其只需在数组中收集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负载,它将成为一个瓶颈(尤其是在移动设备上)。我经常使用这种技术回退到顺序异步。

我经常使用递归(伪)异步函数,它获取异步调用信息列表,并在Ajax完成时使用该列表(减去它的头部,通过切片)调用自己。我还可以在
addtocart
脚本中设置php会话,并在
cart
页面中取消设置。如果会话未设置,则表示这是第一次调用。然而,我不确定这是不是一条路要走!如果复选框数据相互依赖,为什么不能在一次呼叫中发送?不确定是否允许单独的ajax调用。您已经忘记了将
first
设置为false的位。但是,据我所知,$.when将无法保持请求顺序of@Wolff问题中提到“顺序不太重要”,而
承诺
确实是个好主意,并行Ajax调用的负载可能是移动设备上的一个瓶颈(它可以简单地在前几次调用之后丢弃请求)。这就是为什么我在另一个答案中提出了递归异步解决方案,以保持对加载的完全控制。@AntoJSubash顺序并不重要,但第一个必须先发送。我相信顺序现在又是随机的。我也理解这样的OP语句+1 Oops,没有看到问题的BTW部分。请注意,我刚刚将pop()更改为[0],因为它正在处理队列的错误端(将其视为后进先出堆栈…哎哟):)我在
ProcessQueue(队列,回调)行上出错{
未捕获的语法错误:意外的标记{.将
函数
放在它前面解决了这个问题。但是我仍然无法让代码工作。它没有给出任何错误,但我认为
进程队列
没有executed@Timo002:是的,我无法执行您的代码,因此会出现输入错误:)您是否在Chrome中调试或其他东西,以便可以设置断点?如果可以的话一个JSFIDLE模型我可以修复其中的任何错误(看到我把它们放在那里)。这个概念听起来像我以前多次使用过它,但它会是一些我错过的愚蠢细节。一份JSFIDLE中的页面输出HTML副本对初学者来说就行了。