循环中使用JQuery同步Ajax请求

时间:2011-11-11 20:14:35

标签: ajax jquery synchronization

我有以下情况:我需要在循环中生成同步的Ajax请求,并在每次迭代后在div元素中显示返回的结果(在顶部附加前面的结果)。每个请求的响应时间可能不同,但应显示的顺序应与发出的顺序相同。这是一个包含3个请求的示例。让我们说请求“A”需要3秒,“B”需要1秒,“C”需要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 个答案:

答案 0 :(得分:3)

我有两个针对此问题的解决方案建议:

填充生成的div

您可以在循环中生成带有ID的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 :(得分:1)

这可以解决问题

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++);

答案 2 :(得分:0)

我觉得这就是你要找的东西。可能需要一些调整,我对Deferred有点生疏。尽管如此,请阅读它,强大的力量

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()