在连续的AJAX调用中使用async

时间:2014-11-10 21:32:23

标签: javascript jquery

关于使用连续的AJAX调用和异步的问题。由于数据的设置方式,这里有点混乱。我需要返回列表,但是每个查询只返回10个,并且确定列表总数的唯一方法是使用布尔值returnTotal为true而不是false的单独查询。这仅返回列表的数量,而不是列表结果本身。但是,如果我同步运行调用,变量startItem(在每个循环上递增以从下一个列表块开始加载数据)似乎在下一个调用完成之前填充,并且结果会重复。有什么方法可以避免同时作为异步运行?抱歉,如果我的代码荒谬可笑,因为我对jquery相对较新。

$.ajax({
            type: "POST",
            url:server url here,
            data:"creativeID=test&CompanyId=BHSR&StartItem=0&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=true",
            dataType: "html",
            async: false,

            success: function(data) {
                data=convert(data);

                $(data).find('Listing').each(function(){
                    $(this).find('total').each(function(){
                        totalList = $(this).text();
                        totalList = parseInt(totalList);
                        totalPages = totalList/10;
                    });
                }); 
            },
        });

        for (i = 0; i < totalPages; i++){

            $.ajax({
                type: "POST",
                url:server url here,
                data:"creativeID=test&CompanyId=BHSR&StartItem="+startItem+"&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=false",
                dataType: "html",


                success: function(data) {
                    data=convert(data);

                    $(data).find('Listing').each(function(){
                        results_xml.push($(this));
                    });
                    result_index=0;
                    result_image_counter=1;
                    startItem = startItem + 10;
                    popResults();
                },
            });
        }

3 个答案:

答案 0 :(得分:0)

你的意思是没有async:false?

     $.ajax({
type: "POST",
url:server url here,
data:"creativeID=test&CompanyId=BHSR&StartItem=0&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=true",
dataType: "html",

success: function(data) {
console.log('test1'); // first response ok
    data=convert(data);

    $(data).find('Listing').each(function(){
        $(this).find('total').each(function(){
            totalList = $(this).text();
            totalList = parseInt(totalList);
            totalPages = totalList/10;
        });
    }); 
    var startItem=0;
console.log(totalPages); // total page should be equal too "loop" logged

    for (i = 0; i < totalPages; i++){
console.log('loop'); // enter the loop

        $.ajax({
            type: "POST",
            url:server url here,
            data:"creativeID=test&CompanyId=BHSR&StartItem="+startItem+"&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=false",
            dataType: "html",


            success: function(data) {
 console.log('test2'); // number of test 2 = nb of loop = totalPages

                data=convert(data);

                $(data).find('Listing').each(function(){
                    results_xml.push($(this));
                });
                result_index=0;
                result_image_counter=1;
                startItem = startItem + 10;
                popResults();
            },
        });
    }
},
});

答案 1 :(得分:0)

此处的问题是,在收到回复之前,您不会增加startItem。在收到第一个响应之前,您的代码可能会使用startItem === 1发出多个请求,因此您将获得一些非常奇怪的行为(可能会获得重复的响应,并且您只会得到前几页的数据)。

避免使用同步调用,因为它们会占用其他资源(例如javascript)。

在这种情况下,如果您想确保按顺序获取数据,可以将其作为AJAX调用的串行链。

要获得串行行为并享受AJAX的好处,而不是使用循环使您的回调函数在递增startItem后执行下一个AJAX请求。

如果将代码组织到函数中,这会更容易。即:

    function GetData()
    {
      $.ajax({
         type: "POST",
         url:server url here,                     
         data:"creativeID=test&CompanyId=BHSR&StartItem="+startItem+"&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=false",
         dataType: "html", 
         success: GetData_Callback 
      });
    }    
    function GetData_Callback(data)
    {
      data=convert(data);

      $(data).find('Listing').each(function(){
          results_xml.push($(this));
      });
      result_index=0;
      result_image_counter=1;
      startItem += 10; // increment startItem
      popResults();
      if (startItem / 10 < totalPages)
      {
         GetData(); // get next "page" of data
      }
   }
   var startItem = 1; // global variable will be mutated by GetData_Callback
   GetData(); // get first "page" of data

要并行执行此操作通常需要管理并行响应(您可以使用信号量等)。例如(伪代码)你可以做这样的事情:

var pages = [];
var totalPages = GetTotalPages(); // request via ajax like you mentioned (function not shown)
var pagesLoaded = 0;
for(var i = 0; i < totalPages; i++)
{
    GetData(pageIdx);
}
function GetData(pageIdx)
{
    $.ajax({ ..., success: function(data){GetData_Callback(pageIdx,data);}});
}
function GetData_Callback(pageIdx, data)
{
    pages[pageIdx] = data; // assign this specific page of data
    pagesLoaded++;
    if (pagesLoaded === totalPages)
    {
        // fully loaded; trigger event or call function to render, etc.
    }
}

答案 2 :(得分:0)

这里的问题是,在收到响应之前,不要增加startItem。您的代码可能在第一个响应被收到之前使用startItem === 1发出多个请求,因此您将获得一些非常奇怪的行为(可能会获得重复的响应,并且您将只获得前几页数据)。

试试这个。它仍然使用你的循环,但它在循环中增加startItem,然后下一个请求确保所有数据页都被请求。

$.ajax({
            type: "POST",
            url:server url here,
            data:"creativeID=test&CompanyId=BHSR&StartItem=0&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=true",
            dataType: "html",
            async: false,

            success: function(data) {
                data=convert(data);

                $(data).find('Listing').each(function(){
                    $(this).find('total').each(function(){
                        totalList = $(this).text();
                        totalList = parseInt(totalList);
                        totalPages = totalList/10;
                    });
                }); 
            },
        });
        var startItem = 1;
        for (i = 0; i < totalPages; i++){

            $.ajax({
                type: "POST",
                url:server url here,
                data:"creativeID=test&CompanyId=BHSR&StartItem="+startItem+"&streetlocation="+choiceTown+"&Location="+sectCode+"&PriceMin="+choiceMin+"&PriceMax="+choiceMax+"&ListingType="+checkRB+"&OpenHouse=false&NewDev=false&AuthenticationId=id&ReturnTotal=false",
                dataType: "html",


                success: function(data) {
                    data=convert(data);

                    $(data).find('Listing').each(function(){
                        results_xml.push($(this));
                    });
                    result_index=0;
                    result_image_counter=1;
                    popResults();
                },
            });

            // increment start item BEFORE the next request, not in the response
            startItem += 10; // now the next request will be for 11, 21, 31, 41, etc...
        }

您可能希望熟悉您的javascript调试程序以查看自己的行为。