使用`.load()`和/或ajax堆栈延迟

时间:2011-11-23 20:18:36

标签: jquery ajax deferred

我有一个网页,其中包含产品下拉列表和两组过滤器:类型(教育,游戏)和媒体(书籍,CD)。您可以随时从任一过滤器中进行选择,并通过ajax相应地过滤下拉列表。这一切都很有效。

当您选择过滤器时,会在下拉列表上显示跳动,直到ajax结算。问题是,如果在完成解析之前多次更改过滤器,则第一个请求将删除throbber并在第二个请求仍在进行时再次显示下拉列表。这是一个我想解决的小问题。这是javascript:

     $('.radio-filter-type').change(function() {
        $("#products-list").hide();
        $("#products-throbber").show();
        $("#products-container").load(window.location + ' #products-list',
           $("#filter-type").serialize() + '&medium=' + $("#filter-media
              input[name=medium]:checked").val()
           , function () {
              $("#products-list").show();
              $("#products-throbber").hide();
           }
        );
     });

显然,单选按钮会在此期间发生变化,第一个.load()会解析,显示列表并在另一个完成之前隐藏响尾蛇。我可以这样做:

reqCount = 0;
...
.change( ...
   reqCount++;
   .load( ...
      , function () {
         reqCount--;
         if (!reqCount) { //show list and hide throbber

然而,对于Deferred,我觉得必须有一个更清洁的方式。有没有办法将请求添加到当前的Deffered堆栈并等待它们全部解析(它们可以在任意时间添加)。我还注意到.load().then()似乎不起作用。可以Deferred.load()一起使用吗?我使用.load()因为您可以指定仅返回的DOM元素,这很方便。如果没有,是否还有其他方法来管理当前的ajax请求并仅在它们全部完成时才执行操作?

2 个答案:

答案 0 :(得分:0)

为什么不在ajax帖子正在进行时禁用过滤器输入?不太好,但解决了你的问题。

$('.radio-filter-type').change(function() {
    $("#products-list").hide();
    $("#products-throbber").show();
    //disable checkbox
    $("#filter-media input[name=medium]).attr('disabled', 'disabled');
    $("#products-container").load(window.location + ' #products-list',
       $("#filter-type").serialize() + '&medium=' + $("#filter-media
          input[name=medium]:checked").val()
       , function () {
          $("#products-list").show();
          $("#products-throbber").hide();
          //renable checkbox
          $("#filter-media input[name=medium]).removeAttr('disabled');
       }
    );
 });

答案 1 :(得分:0)

执行此操作的方法是,如果过滤器的值与原始请求的值不同,则取消成功结束ajax请求时的操作。这是对代码可能是什么样子的尝试:

$('.radio-filter-type').change(function() {
    var filterStateAtChange = $("#filter-media input[name=medium]).is(':checked');

    $("#products-list").hide();
    $("#products-throbber").show();
    $.get(window.location + ' #products-list',
        $("#filter-type").serialize() + '&medium=' + $("#filter-media
          input[name=medium]:checked").val()
       , 
      function (html) {
          //cancel (do nothing) if the value of the checkbox now is not equal to what it was when request originated
          if (filterStateAtChange === $("#filter-media input[name=medium]).is(':checked')) {
              $("#products-container").html(html)
              $("#products-list").show();
              $("#products-throbber").hide();
          }

       }
    );
 });