Подтвердить что ты не робот

Как я могу сделать партии ajax-запросов в jQuery?

Мне интересно, как делать ajax-вызовы в группах по n.

Здесь мой прецедент:

У меня есть таблица, в которой отображаются данные об использовании. Вы можете просверлить каждую строку, и если каждая строка имеет общий атрибут, вы можете глубже погрузиться в глубину, вы можете сразу развернуть все их. Для каждой строки выполняется вызов ajax для извлечения данных, добавляемых в таблицу.

В некоторых случаях может сверяться до 50 строк. Как вы можете себе представить, это вызывает большой стресс на сервере. Как лучше всего я могу отправлять эти вызовы в меньших партиях, которые ждут от партии до их запуска?

Я знаю, что есть плагины вроде очереди сообщений jquery, которые могут потенциально помочь мне, но это рабочий проект, поэтому мы хотели бы как можно больше избежать плагинов.

4b9b3361

Ответ 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);
        }
    });
}