【问题标题】:How can I a group jQuery AJAX queries?如何对 jQuery AJAX 查询进行分组?
【发布时间】:2011-12-22 10:34:06
【问题描述】:

我有一些看起来像这样的代码(我省略了对问题不重要的部分):

$.ajax({  
    type: "POST",  
    url:  "prepXML.php",  
    data: "method=getartists&user=" + userName + "&amount=" + amount,  
    dataType: "xml",
    success: function(xml) { 
        $("artist", xml).each(function(){
            // calculate and output some stuff and then call getTracks()
            getTracks(artistName, artistNamePOST, artistPlaycount, divId, artistId);
        }); 
    }
});  

function getTracks(artistName, artistNamePost, artistPlaycount, divId, artistId){
    $.ajax({  
        type: "POST",  
        url:  "prepXML.php",  
        data: "method=gettracks&user=" + userName + "&artist=" + artistNamePOST + "&playcount=" + artistPlaycount,  
        dataType: "xml",
        success: function(xml){
            // calculate and output some stuff
        });                     
    }
});  

当它运行时,它会调用 getTracks() 五十次,并在很短的时间内产生相当多的(服务器)CPU 负载,直到全部完成。我想做的是一次将 AJAX getTrack() 查询分组为例如 5 个,等到这五个完成,然后调用接下来的五个,等到接下来的五个完成,再调用接下来的五个等等。这样做的目的是基本上同时进行更少的查询(更少和更均匀地分布 CPU 负载)。

我不确定如何或什至可以做到这一点,因为它在某种程度上超越了 AJAX 的意义,但如果可能的话,我仍然希望完成这项工作。有人可以指出我正确的方向吗?谢谢。

为了更好地了解我需要这个以及应用程序的作用,这里有一个指向 app 的链接。可以使用任何 lastfm nick 来试用它(如果你没有,你可以使用我的 - “pootzko”)。我希望允许我将链接放在帖子中(?),如果没有,请随意删除它..

【问题讨论】:

  • 当您执行method=getartist 时,为什么不只返回一组曲目以及您的艺术家数据,那么您只需要执行一次服务器调用(每个艺术家)。也许有一个名为getartistwithtracks的方法
  • @musefan - 这与 lastfm api 一起使用,其中 getartists 首先查询 lastfm 并获取最受听的 arist 列表,之后它必须对 lastfm 进行新的单独查询以获取有关每个轨道的信息艺术家。
  • 看这个:bunch of ajax call

标签: javascript jquery synchronization grouping


【解决方案1】:

我会考虑只检索用户点击的艺术家的曲目信息。或者可能通过单个请求检索所有数据(可能在检索到数据后通过setTimeout() 批量处理)。

但类似以下内容的方法可能一次只能执行五个请求:

$.ajax({  
    type: "POST",  
    url:  "prepXML.php",  
    data: "method=getartists&user=" + userName + "&amount=" + amount,  
    dataType: "xml",
    success: function(xml) { 
      var artists = $("artist", xml),
          i = 0,
          c = 0;

      function getTracksComplete() {
         if (--c === 0)
            nextBatch();
      }

      function nextBatch() {
         for(; c < 5 && i < artists.length; i++, c++) {
            // artists[i] is the current artist record    
            // calculate and output some stuff and then call getTracks()
            getTracks(artistName, artistNamePOST, artistPlaycount, divId, artistId,
                      getTracksComplete); 
         }
      }

      // Optional - if you need to calculate statistics on all the artists
      // then do that here before starting the batches of getTracks calls
      artists.each(function() { /* do something */ });

      // Kick of the first batch of 5
      nextBatch();
   } 
});

function getTracks(artistName, artistNamePost, artistPlaycount, divId, artistId,
                   callback){
    $.ajax({  
        type: "POST",  
        url:  "prepXML.php",  
        data: "method=gettracks&user=" + userName + "&artist=" + artistNamePOST + "&playcount=" + artistPlaycount,  
        dataType: "xml",
        success: function(xml){
            // calculate and output some stuff
        },
        complete : function() {
            if (callback) callback();
        });                     
    }
});

以上只是我的想法(所以我没有时间构建它以缩放或绘制它),但我的想法是,而不是使用 .each() 循环遍历所有艺术家我们将立即缓存 jQuery 对象并一次执行一些操作。调用函数nextBatch()(它是成功处理程序的本地函数,因此可以访问局部变量)将运行一个循环,该循环仅调用getTracks() 5 次,但从我们上次中断的位置开始处理。同时,getTracks() 已略微更新以接受回调函数,因此当 its ajax 调用完成时(请注意,我们在完成时执行此操作而不是在发生错误时成功)它可以让主进程知道它已经完成了。在回调中,我们会跟踪有多少人已完成,以及他们何时再次致电nextBatch()

【讨论】:

    【解决方案2】:

    要么在从getartists 返回的数据中包含所有曲目信息,要么仅在有人想要查看特定艺术家的曲目时调用getTracks

    例如

    显示所有艺术家,并有一个“查看曲目”选项。只有单击此按钮后,您才能获得曲目。

    对我来说,这是最好的选择,因为如果您要为所有艺术家加载所有曲目,那么可能不需要大量数据。没有人会想要查看所有艺术家和所有艺术家的曲目(除非特别想要)。

    【讨论】:

    • 问题是实际上所有的数据都是用来计算一些统计数据的。
    • 如果它只是用于计算统计数据然后显示统计数据,那么在getartists中完成这一切并返回统计数据不是更好吗?
    • 那么会发生什么是应用程序“挂起”30-40 秒,直到全部计算出来,所以我会说纯 ajax 比这更好。如果可能的话,我只是想“改善”这一点。我在我的原始帖子中放置了一个指向该应用程序的链接,以便更好地了解它的作用,如果这有帮助的话。
    【解决方案3】:

    我的解决方案是将所有艺术家数据处理到数组中,然后以 5 个批次开始执行 .ajax() 请求。当这 5 个请求完成后,执行下一批,等等。

    HERE 是一个工作演示。

    // just success changed
    $.ajax({  
      type: "POST",  
      url:  "prepXML.php",  
      data: "method=getartists&user=" + userName + "&amount=" + amount,  
      dataType: "xml",
      success: function(xml) {
        var data = [];
        // prepare the data
        $("artist", xml).each(function(){
            data.push({ name: artistName /** rest of data */ } );
        }); 
        // start processing the data
        processData(data, 0);
      }
    });  
    
    // process the data by sending requests starting from index
    function process(data, index) {
      var xhrs = [];
      for (var i = index; i < index + 5 && i < data.length; i++) {
        (function(data) {
           xhrs.push($.ajax({  
             type: "POST",  
             url:  "prepXML.php",  
             data: "method=gettracks&user=" + data.name /** rest of the data */  
             dataType: "xml",
             success: function(xml) {
               // calculate and output some stuff
             }
           }));
         })(data[i]);
       }
    
      // when current xhrs are finished, start next batch
      $.when.apply(this, xhrs).then(function() { 
        index += 5; 
        if (index < data.length) {
          process(data, index); 
        }
      });
    }
    

    【讨论】:

    • +1 表示可行的解决方案/想法。我选择了@nnnnnn 的解决方案,因为对我来说它更容易理解和实施。感谢您的努力。 :)
    【解决方案4】:

    很难清楚地理解您的应用程序的逻辑,但我认为更好的方法应该是预先收集您需要发送的所有数据(JSON 对象中的 50 个条目),然后只调用一次 getTracks 函数,只传递一个JSON 对象。

    【讨论】:

      猜你喜欢
      • 2022-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 2021-02-17
      • 2013-02-17
      相关资源
      最近更新 更多