如何在jQuery中制作批量的ajax请求?

时间:2011-08-08 18:03:19

标签: jquery ajax

我想知道如何在n组中进行ajax调用。

这是我的用例:

我有一个显示使用情况数据的表格。您可以深入到每一行,如果每行都有一个公共属性,您可以深入钻取,您可以选择一次钻入所有行。对于每一行,进行ajax调用以获取要附加到表的数据。

在某些情况下,最多可以同时钻取50行。可以想象,这给服务器带来了很大的压力。我最好能够以较小的批次发送这些电话,这些批次在等待批处理之前发射它们吗?

我知道有像jquery消息队列这样的插件可能会帮助我,但这是一个工作项目,所以我们希望尽可能地避免使用插件。

4 个答案:

答案 0 :(得分:18)

您可以查看使用jQuery.when,它允许您在所有请求完成后执行回调函数。

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3"))
 .done(function(data1,  data2, data3){
         // Do something with the data
 });

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3"))
.then(successCallback, errorHandler);

有关详细信息,请参阅以下post

此外,我不确定您对使用插件的担忧应该受到您在工作环境中的影响,特别是如果它简化了您的工作。因此可以提高工作效率。当然,您必须仔细选择插件,因为质量和长期维护可能是一个问题。

答案 1 :(得分:7)

使用jQuery的Ajax调用通常是异步的。因此,如果您有50行,jQuery将异步发送所有50个请求 - 当您从服务器获得响应时,您无法控制处理顺序。

您可以在async: false调用上使用$.ajax,这样当您遍历行时,只有一个请求会发送到服务器:

$.ajax({
    url: location,
    data: params,
    async: false,
    success: function(msg) { // do something}
});

此方法(async: false)的问题是用户可能会遇到“冻结”或无响应的页面。

另一种方法是在JavaScript中使用递归,这样调用仍然是异步的,但是ajax调用仍然等待每行的成功事件,如下所示:

var maxRows = 50;

function myFunc(index) {
   $.ajax({
       url: location,
       data: params,
       async: true,
       success: function(msg) { 
            if (index < maxRows) {
               // do something
            }
            else {
               return; //index equals maxRows--stop the recursion
            }
            index++;
            myFunc(index); //call the function again
       }
   });

   $(document).ready(function() {
       myFunc(0);      
   });
}

答案 2 :(得分:3)

我同意eicto:如果你不能整合另一个,请建立自己的消息管理器。这是我在一个小小的裂缝:

var AjaxQueue = function(max) {
  this.max = max;
  this.requests = [];
  this.current = 0;
}

AjaxQueue.prototype.ajax = function(opts) {
  var queue = this;
  opts.complete = function(jqXHR, textStatus) {
    queue.current -= 1;
    queue.send();
  };
  this.requests.push(opts);
  this.send();
}

AjaxQueue.prototype.send = function(opts) {
  while (this.current < this.max && this.requests.length > 0) {
    $.ajax(this.requests.unshift());
    this.current += 1;
  }
}

我还没有尝试过使用它,所以肯定会有bug。此外,它假设您没有使用complete选项。它只是覆盖它。如果你是,你可以检查它,并确保仍然可以调用以前的完整功能。

答案 3 :(得分:0)

递归批量调用对我有用。但是因为我获得了4K的XHR2 blob并且在IndexedDB(PouchDB)中保存了每个。我有XHR2和IDB看跌期权的线程。所以我必须更复杂一点:

     for (var i in info.LayerInfo) {
        var imageType = (info.LayerInfo[i].Class == "BASE") ? "jpg" : "png";
        info.LayerInfo[i].SaveCount = 0;
        getLayer(0, info, info.LayerInfo[i], info.LayerInfo[i].Path, imageType);
    }
}

function getLayer(index, info, layer, base, imageType) {
    if (layer.Files.length == 0) {
        console.log("Thread done: " + index + " SaveCount: " + layer.SaveCount);
        return;
    }
    var val = layer.Files.shift();
    var path = base + "/" + val.id + "." + imageType;
    $xhr.ajax({
        url: path,
        dataType: "blob",
        success: function (data) {
            console.log("fetched: ", layer.Type + "-" + val.id);
            saveBlob(data, val.size, val.id, layer.Type, index, info, layer, base, imageType);
            if (index < maxThreads - 1) {
                getLayer(++index, info, layer, base, imageType);
            } else {
                return;
            }
        }
    });
}

function saveBlob(blob, length, id, layerID, index, info, layer, base, imageType) {
    if (blob.size != length) {
        console.error("Blob Length found: ", blob.size, " expected: ", length);
    }
    var blobID = layerID + "-" + id;
    var type = blob.type;
    DB.putAttachment(blobID + "/pic", blob, type, function (err, response) {
        if (err) {
            console.error("Could store blob: error: " + err.error + " reason: " + err.reason + " status: " + err.status);
        } else {
            console.log("saved: ", response.id + " rev: " + response.rev);
            layer.SaveCount++;
            getLayer(index, info, layer, base, imageType);
        }
    });
}