Постановка в очередь / регулирование запросов jQuery ajax

#javascript #jquery #ajax #jquery-deferred

#javascript #jquery #ajax #jquery-отложенный

Вопрос:

Мне нужно запустить несколько ajax-запросов на сервере, а затем выполнить обратный вызов, когда они будут завершены. Обычно это было бы легко сделать с помощью jQuery deferred.done() . Однако, чтобы избежать перегрузки сервера, я ставлю запросы в очередь и запускаю по одному каждые X миллисекунд.

например

 var promisesList = [];

var addToQueue = function(workflow) {
    workflowQueue.push(workflow);
  }

var startWorkflow = function(workflow) {
    return $.ajax($endointURL, {
      type: "POST",
      data: {
        action: workflow.id
      },
      success: function() {
      },
      error: function(jqXHR, textStatus, errorThrown) {
      }
    });
  };

  var startWorkflows = function() {
    var promisesList = [];
    if (workflowQueue.length > 0) {
      var workflow = workflowQueue.shift();
      promisesList.push(startWorkflow(workflow));
      setTimeout(startWorkflows, delay);
    }
  };

startWorkflows();
$.when(promisesList).done(function(){
  //do stuff
});
  

Проблема с этим заключается в том, что promisesList массив изначально пуст, поэтому done() обратный вызов запускается немедленно, а затем setTimeout() запросы ajax начинают отправляться с помощью. Существует ли простой способ изначально создавать запросы ajax и как бы «приостанавливать» их, а затем запускать с помощью setTimeout() .

Я нашел различные реализации регулирования / очереди для последовательного запуска запросов ajax, но я рад, что они запускаются параллельно, просто с задержкой на них.

Комментарии:

1. setTimeout с произвольной задержкой не вариант?

2. Я использую setTimout() , проблема заключается в обработке deferred объектов.

3. Я предполагаю, что вам нужно обрабатывать часть $.when для каждого запроса… или что вы ждете, пока все не будут отправлены, а затем делаете, когда …

Ответ №1:

Первое, на что вы натыкаетесь, это то, что when() это не работает таким образом с массивами. Он принимает произвольный список обещаний, поэтому вы можете обойти это, применив массив с помощью:

 $.when.apply(null, promiseList).done(function(){
    // Do something
    // use the `arguments` magic property to get an ordered list of results
});
  

Во-вторых, метод регулирования может быть выполнен с помощью параметра $.ajax {delay:timeInSeconds}, но я предложил решение, которое устанавливает новую отсрочку, которая немедленно возвращается (для сохранения порядка), но разрешается по истечении времени ожидания.

Смотрите http://jsfiddle.net/9Acb2/1 для интерактивного примера

Комментарии:

1. (a) Я был уверен, что это $.when() сработает именно так! Проверено, и вы правы, он не принимает массивы. Странно, кажется очевидной вещью для этого. (b) я не вижу delay параметра в документах jQ для запросов ajax? (c) Ваша скрипка идеальна, я не думал о создании $.Deferreds() такого вручную. Большое спасибо!