Как я могу сделать пакеты запросов ajax в jQuery? - PullRequest
15 голосов
/ 08 августа 2011

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

Вот мой вариант использования:

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

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

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

Ответы [ 4 ]

18 голосов
/ 08 августа 2011

Вы можете взглянуть на использование 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);

См. Следующую запись для получения дополнительной информации.

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

7 голосов
/ 08 августа 2011

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 голосов
/ 08 августа 2011

Я согласен с 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.Это просто отменяет это.Если вы, вы можете проверить это и убедиться, что предыдущие полные функции все еще вызывают.

0 голосов
/ 19 июня 2013

Рекурсивная группировка звонков у меня работает.Но так как я получаю 4 КБ объектов 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);
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...