JavaScript / jQuery如何在多个ajax响应上调用回调函数

时间:2016-03-29 09:07:11

标签: javascript jquery ajax callback

我知道ajax中的a意味着异步,因此无法保证我的响应将返回哪个顺序,事实上,期望最大有效负载最后返回是合理的。

然而我的问题是关于回调。有时当我发现我的回复以不同的顺序返回时,会调用“错误的”回调。

采取以下功能。 有一些值(rangesize, dropskus, limit)(下面评论),每个调用都是唯一的,并在每个调用的成功回调中定义。当我运行脚本并发送5个呼叫时,如果它们确实按照发送它们的顺序返回。假设最大的响应是第二次调用,响应最后返回并调用最后一个回调函数。

所以我的问题:

JavaScript / jQuery是否或应该知道在返回多个响应时要调用哪个回调函数?

或者我使用同步通话会更好吗?

其他说明: 在chrome中调试时,我注意到响应的控制台日志说filename.js:linenumber。以前当我使用多个ajax调用时,控制台日志会说VM12*:linenumber。我不知道这与我面临的问题有什么关系,但我确实注意到,在这种情况下,总是会调用正确的回调。

function generateReview(){

  var subcategories = subcatstring.split(",");

  $("#rangereviewtable").html("");
  $("#rangereviewtable").append(thead);

  var i = 0;
  var iterations = subcategories.length;
  $.each(subcategories, function(key, value) {

        var postdata = {group: group,
                        class: rrclass,
                        category: category,
                        subcategory: value,
                        period: period,
                        periodval: periodval,
                        stores: storesarray};
        console.log(postdata);

        $.ajax({
                url: "ajaxrangereview.php",
                type: "post",
                dataType: 'json',
                data: postdata,
                success: function (response) {

                  //VALUES UNIQUE TO EACH CALL
                  var rangesize = parseInt($("#rangesize" + i).text());
                  console.log("range size: " + rangesize);
                  var dropskus = parseInt($("#dropskus" + i).text());
                  console.log("dropskus: " + dropskus);
                  var limit = rangesize - dropskus;
                  console.log("limit: " + limit);

                  console.log(response);

                  var rrtable = "";

                        $.each(response, function(i, item) {

                            rrtable += "<tr>";
                              rrtable += "<td class='rangereviewtext'>" + item.category + "</td>";
                              rrtable += "<td class='rangereviewtext'>" + item.subcategory + "</td>";
                              rrtable += "<td class='rangereviewtext'>" + item.brand + "</td>";
                              rrtable += "<td class='rangereviewtext'>" + item.sku + " - " + item.product + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.py3.toLocaleString("en") + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.py2.toLocaleString("en") + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.py1.toLocaleString("en") + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.average.toLocaleString("en") + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.sales.toLocaleString("en") + "</td>";
                              rrtable += "<td class='rangereviewnumber'>" + item.share + "%</td>";
                              rrtable += "<td>&#x2714</td>";

                              if(limit >= item.idnum){

                                  rrtable += "<td>&#x2714</td>";
                                  rrtable += "<td class='checkboxcell' onClick=\"toggleCheckMark(this, '" + item.brand + "')\">&#x2714</td>";

                              } else {

                                  rrtable += "<td></td>";
                                  rrtable += "<td class='checkboxcell' onClick=\"toggleCheckMark(this, '" + item.brand + "')\"></td>";

                              }

                            rrtable += "</tr>";
                        });
                    // increment iterations
                    i += 1;

                    $("#rangereviewtable").append(rrtable);

                    if(i == iterations){

                      var headimage = "<img src='http://url.com/images/oimage.png' width='63.5px' height='76px'>";
                      var table = $("#rangereviewtable").DataTable({
                                                                    buttons: [{extend: 'excelHtml5', title: 'Range Review', text: 'Export to Excel'},
                                                                              {extend: 'print', title: 'Range Review', message: headimage}],
                                                                  });
                      //insert export to excel button into #rrbuttons div above actual table.
                      table.buttons().container().appendTo( $('#rrbuttons') );

                      $("#rangereviewpanel").show();
                      $("#generatebutton").hide();
                      $("#loadbutton").hide();
                      $("#saveasbutton").show();
                      generateReviewSummary(summaryarray);

                    } else {

                      //do nothing not all iterations complete

                    }

                    },
                error: function(jqXHR, textStatus, errorThrown) {

                    i+= 1;
                    console.log(textStatus, errorThrown);
                  }
            });
  });
}

2 个答案:

答案 0 :(得分:1)

在你的具体情况下,我认为它会正常工作(你的代码就像这样):

LastCheckedTime

此代码将输出数字0..9;
但是,让我们看另一个例子:

var j = 0;
for (var i = 0; i < 10; i++) {
    setTimeout(function () {
        console.log(j);
        j++
    }, 1000)
}

输出9..9
因此,在同步循环内调用异步函数并不安全。您可以使用async.each(https://github.com/caolan/async#each)或承诺来处理它。

答案 1 :(得分:1)

JavaScript / jQuery确切地知道要调用哪个回调,并且正确地这样做。

您需要了解有关JavaScript闭包和范围的更多信息。

我不确定你的意思是错误的&#39;并且&#39;对&#39;关于你的逻辑的回调。如果您希望在收到对上一个请求的响应时启动特殊逻辑,那么您可以尝试将i的使用替换为对key的引用相反(或者如果我正确地阅读你的逻辑,你可能想要使用key + 1