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

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

这是我的用例:

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

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

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

您可以查看使用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 。

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

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

您可以在$.ajax调用上使用async: false ,以便在循环遍历行时只向服务器发送一个请求:

 $.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); }); } 

我同意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选项。 它只是覆盖它。 如果你是,你可以检查它,并确保仍然调用以前的完整function。

递归批处理呼叫对我有用。 但是因为我获得了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); } }); }