简体   繁体   English

在连续的AJAX调用中使用异步

[英]Use of async on successive AJAX calls

Question here about use of successive AJAX calls and async. 在此询问有关连续AJAX调用和异步使用的问题。 Its a bit messed here because of how the data is set up. 由于数据的设置方式,这里有些混乱。 I need to return listings, but the sever only returns 10 per query, and the only way to determine the total number of listings is a separate query with the boolean returnTotal as true instead of false. 我需要返回列表,但服务器每个查询仅返回10,并且确定列表总数的唯一方法是使用boolean returnTotal为true而不是false的单独查询。 This returns the number of listings only, and not the listing results themselves. 这仅返回列表的数量,而不返回列表本身。 However, if I run the calls synchronously, the variable startItem (which increments on each loop to load data starting at the next block of listings) doesn't seem to populate before the next call finishes, and results get duplicated. 但是,如果我同步运行调用,则变量startItem(在每个循环中递增,以从清单的下一个块开始加载数据)在下一个调用完成之前似乎不会填充,并且结果重复。 Any way to avoid running both as async? 有什么办法可以避免同时以异步方式运行? Apologies if my code is batshit ridiculous, as I'm relatively new to jquery. 如果我的代码是荒谬的,我很抱歉,因为我对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();
                },
            });
        }

Do you just mean without the 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();
            },
        });
    }
},
});

The problem here is that you do not increment startItem until you receive a response. 这里的问题是,直到收到响应,您才递增startItem Your code is probably making multiple requests with startItem === 1 before the first response is even received, and so you will get some really weird behavior (probably will get duplicate responses, and you will only get the first few pages of data). 您的代码可能甚至在收到第一个响应之前就用startItem === 1发出多个请求,因此您将获得一些非常奇怪的行为(可能会得到重复的响应,并且只会得到数据的前几页)。

Avoid using synchronous calls because they will tie up other resources (like javascript). 避免使用同步调用,因为它们会占用其他资源(例如javascript)。

In this case if you want to insure that you get the data in order, you can make it a serial chain of AJAX calls. 在这种情况下,如果要确保按顺序获取数据,可以使其成为AJAX调用的串行链。

To get serial behavior and enjoy the benefits of AJAX, instead of using a loop make your callback function do the next AJAX request after incrementing startItem . 为了获得串行行为并享受AJAX的好处,而不是使用循环,而是使您的回调函数在增加startItem之后执行下一个AJAX请求。

This is easier if you organize your code into functions. 如果将代码组织到函数中,这会更容易。 To wit: 以机智:

    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

To do this in parallel typically requires management of the parallel responses (you can use semaphores, etc.). 并行执行此操作通常需要管理并行响应(您可以使用信号灯等)。 For example (psuedo code) you could do something like this: 例如(伪代码),您可以执行以下操作:

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.
    }
}

The problem here is that you do not increment startItem until you receive a response. 这里的问题是,直到收到响应,您才递增startItem。 Your code is probably making multiple requests with startItem === 1 before the first response is even received, and so you will get some really weird behavior (probably will get duplicate responses, and you will only get the first few pages of data). 您的代码可能甚至在收到第一个响应之前就用startItem === 1发出多个请求,因此您将获得一些非常奇怪的行为(可能会得到重复的响应,并且只会得到数据的前几页)。

Try this instead. 试试这个吧。 It still uses your loop but it increments startItem in the loop before the next request is made to insure that all pages of data are requested. 它仍然使用您的循环,但会在发出下一个请求之前在循环中递增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...
        }

You may want to get familiar with your javascript debugger to see the behavior for yourself. 您可能想熟悉您的JavaScript调试器,以亲自了解行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM