Как я могу сделать партии ajax-запросов в jQuery?
Мне интересно, как делать ajax-вызовы в группах по n.
Здесь мой прецедент:
У меня есть таблица, в которой отображаются данные об использовании. Вы можете просверлить каждую строку, и если каждая строка имеет общий атрибут, вы можете глубже погрузиться в глубину, вы можете сразу развернуть все их. Для каждой строки выполняется вызов ajax для извлечения данных, добавляемых в таблицу.
В некоторых случаях может сверяться до 50 строк. Как вы можете себе представить, это вызывает большой стресс на сервере. Как лучше всего я могу отправлять эти вызовы в меньших партиях, которые ждут от партии до их запуска?
Я знаю, что есть плагины вроде очереди сообщений jquery, которые могут потенциально помочь мне, но это рабочий проект, поэтому мы хотели бы как можно больше избежать плагинов.
Ответы
Ответ 1
Вы можете взглянуть на 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);
Дополнительную информацию см. в .
Кроме того, я не уверен, что ваше понимание использования плагина должно зависеть от того, что вы работаете в рабочей среде, особенно если это упрощает вашу работу. Следовательно, позволяет быть более продуктивным. Конечно, вы должны тщательно выбирать свои плагины, так как качество и долгосрочное обслуживание могут быть проблемой.
Ответ 2
Ajax-вызовы с использованием jQuery обычно асинхронны. Итак, если у вас есть 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);
});
}
Ответ 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;
}
}
Я еще не пробовал использовать его, поэтому обязательно будут ошибки. Также предполагается, что вы не используете опцию complete
. Он просто переопределяет это. Если вы, вы можете проверить его и убедиться, что предыдущие полные функции все еще вызываются.
Ответ 4
Рекурсивная пакетная обработка вызовов работает для меня. Но так как я получаю 4K капель XHR2 и сохраняю каждый в 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);
}
});
}