我想知道如何在n组中进行ajax调用。
这是我的用例:
我有一个显示使用情况数据的表格。您可以深入到每一行,如果每行都有一个公共属性,您可以深入钻取,您可以选择一次钻入所有行。对于每一行,进行ajax调用以获取要附加到表的数据。
在某些情况下,最多可以同时钻取50行。可以想象,这给服务器带来了很大的压力。我最好能够以较小的批次发送这些电话,这些批次在等待批处理之前发射它们吗?
我知道有像jquery消息队列这样的插件可能会帮助我,但这是一个工作项目,所以我们希望尽可能地避免使用插件。
答案 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);
}
});
}