Синхронизированные запросы Ajax с JQuery в цикле - PullRequest
2 голосов
/ 12 ноября 2011

У меня следующая ситуация: мне нужно делать синхронизированные запросы Ajax внутри цикла и отображать возвращаемый результат после каждой итерации в элементе div (добавляется сверху, а предыдущие результаты внизу). Время ответа на каждый запрос может быть разным, но порядок, в котором он должен отображаться, должен быть таким же, как и отправленный. Вот пример с 3 запросами. Допустим, запросу «А» нужно 3 секунды, «В» - 1 секунда, а «С» - 5 секунд. Порядок, в котором я хочу отобразить результат: A, B, C, поскольку запросы были выполнены, но код, который я использую, показывает результаты в B, A, C.

Вот код (запрос JQuery Ajax):

$(document).ready(function(){ 
  var json = document.getElementById("hCategories").value;
  var categories = eval( '(' + json + ')' );

  for(curCat in categories) {
    curCatKey = categories[curCat]['grKey'];

    $.ajax({
      type: "POST",
      url: "get_results.php",
      data: "category=" + escape(curCatKey) + 
            "&search=" + escape($("#hQuery").val()),
      timeout: 8000,
      async: false, 

      success: function(data) {
        $("#content").append(data);
      }
  });
});

Я думал, что это сработает с "async: false", но затем он ждет, пока не завершится каждый вызов Ajax, и представит результаты после цикла. Я надеюсь, что некоторые из вас могут указать на некоторые различные решения, я в значительной степени застрял.

Спасибо заранее, Ура Крис

РЕДАКТИРОВАТЬ: Спасибо за все возможные решения, я попробую их сейчас один за другим и вернусь с тем, который соответствует моей проблеме.

Ответы [ 3 ]

3 голосов
/ 12 ноября 2011

У меня есть два решения этой проблемы:

Заполнить созданные divs

Вы можете сгенерировать элементы div с идентификаторами в цикле и заполнить их после завершения запроса:

$(document).ready(function() {
    var json = document.getElementById("hCategories").value;
    var categories = eval('(' + json + ')');

    for (curCat in categories) {
        (function(curCat) {
            var curCatKey = categories[curCat]['grKey'];
            $('#content').append('<div id="category-"' + escape(curCat) + '/>');

            $.ajax({
                type: "POST",
                url: "get_results.php",
                data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val()),

                success: function(data) {
                    $("#category-" + escape(curCat)).html(data);
                }
            });
        })(curCat);
    }
});

Или использовать отложенный

Вы можете хранить jqXHR объекты в массиве и использовать deferred для вызова функций успеха по порядку, когда все вызовы завершены.

$(document).ready(function() {
    var json = document.getElementById("hCategories").value;
    var categories = eval('(' + json + ')');
    var requests;

    for (curCat in categories) {
        var curCatKey = categories[curCat]['grKey'];

        requests.push($.ajax({
            type: "POST",
            url: "get_results.php",
            data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val())
        }));
    }

    $.when.apply(requests).done(function() {
        for (i in requests) {
            requests[i].success(function(data) {
                $("#content").append(data);
            });
        }
    });
});

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

1 голос
/ 12 ноября 2011

Это бы сработало

var results = [];
var idx = 0;

for(curCat in categories) {
    curCatKey = categories[curCat]['grKey'];

    (function( i ) {
        $.ajax({
          type: "POST",
          url: "get_results.php",
          data: "category=" + escape(curCatKey) + 
              "&search=" + escape($("#hQuery").val()),
          timeout: 8000,
          async: false, 
          success: function(data) {
            results[i] = data;
            if (i == idx - 1) { // last one
               for (var j=0; j < results.length; j++) {
                   $("#content").append(results[j]);
               }
            }
          }
       });
    })(idx++);
0 голосов
/ 12 ноября 2011

Я думаю, что-то вроде этого - то, что вы ищете. Может понадобиться немного подправить, я немного подзабыл на Отложенном. Читайте об этом, хотя, могучий мощный

deferred = $.Deferred()
for(curCat in categories) {
  deferred.pipe(
    function(resp){
      postData = {} // set up your data...
      return $.post("get_results.php", {data: postData, timeout: 8000})
              .done(function(content){ $("#content").append(content) })
    })
  )
}

// Trigger the whole chain of requests
deferred.resolve()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...