2010-07-14 58 views
0

我写了一些代码,你选择一个国家后过滤省/州选择字段:如何避免3个Ajax调用?

var cache = {}; 

    function updateProvinceOptions($select, values, initial) { 
      for(i in values) { 
        $select.append('<option value="'+values[i][0]+'">'+values[i][1]+'</option>'); 
      } 
      $select.val(initial).trigger('change'); 
    } 

    $('<select class="province" />').insertBefore('.province').change(function() { // insert select boxes beside hidden province inputs 
      $(this).siblings('input.province').val($(this).val()); // update hidden input with current value 
    }); 

    $('.country').change(function() { 
      var $countrySel = $(this); 
      var $provSel = $countrySel.parent().parent().next().children('td').children('select.province'); 
      var $provInput = $provSel.siblings('input.province'); 
      var country = $countrySel.val(); 
      var province = $provInput.val(); 

      $provSel.empty(); 
      if(country in cache) { 
        updateProvinceOptions($provSel, cache[country], province); 
      } 
      else { 
        $provSel.addClass('loading'); 
        $.getJSON('/get-provinces.json', {'country':country}, function(provinces) { 
          $provSel.removeClass('loading'); 
          cache[country] = provinces; 
          updateProvinceOptions($provSel, provinces, province); 
        }); 
      } 
    }).trigger('change'); 

它甚至缓存的结果,这样,如果你说,再次选择加拿大,当时的美国,然后加拿大,它不需要再次在加拿大省份列表中找到服务器。不过,我同时在页面上显示了其中的3个。当页面首次加载时,缓存中没有任何内容,因此,所有3个em都打到了服务器以获取省份列表,因为没有ajax调用返回。

是否有一个相对简单的方法告诉它“等待”该国家的ajax呼叫是否正在进行中?或者我应该甚至打扰?

回答

1

没关系..应对自旋子......这并不难后添加一个“等待”队列时再次回答我自己的问题全部:

var cache = {}; 
    var retrieving = {}; 

    function updateProvinceOptions($select, values, initial) { 
      for(i in values) { 
        $select.append('<option value="'+values[i][0]+'">'+values[i][1]+'</option>'); 
      } 
      $select.val(initial).trigger('change'); 
    } 

    $('<select class="province" />').insertBefore('.province').change(function() { // insert select boxes beside hidden province inputs 
      $(this).siblings('input.province').val($(this).val()); // update hidden input with current value 
    }); 

    $('.country').change(function() { 
      var $countrySel = $(this); 
      var $provSel = $countrySel.closest('tr').next('tr').find('select.province'); 
      var $provInput = $provSel.siblings('input.province'); 
      var country = $countrySel.val(); 
      var province = $provInput.val(); 

      $provSel.empty(); 
      if(country in cache) { 
        updateProvinceOptions($provSel, cache[country], province); 
      } else if(country in retrieving) { 
        retrieving[country].push($provSel); 
      } 
      else { 
        retrieving[country] = [$provSel] 
        $provSel.addClass('loading'); 
        $.getJSON('/get-provinces.json', {'country':country}, function(provinces) { 
          $provSel.removeClass('loading'); 
          cache[country] = provinces; 
          while(retrieving[country].length > 0) { 
            $select = retrieving[country].pop(); 
            updateProvinceOptions($select, provinces, province);  
          }        
        }); 
      } 
    }).trigger('change'); 
2

我会说可能会添加一个属性缓存或一些其他对象以外的方法来指示是否缓存当前正在加载。在调用ajax方法之前将该值设置为true,然后在ajax调用的成功函数完成后将其设置为false。如果这是真的,那么你跳过任何后续调用,直到该值为假。

只是一种可能的解决方案。

+0

是的,真/假部分是简单的位(确定数据是否已被请求)......但是如何插入延迟?我想你会添加一个“waitingOn”队列......并且当ajax complete方法激发时,你遍历所有的服务员...... – mpen 2010-07-14 23:44:51

+0

看起来你已经想通了。很高兴我可以帮忙,如果我做了。看起来像你自己想出来的。只需要一个小指针。 – spinon 2010-07-15 00:14:22

0

我会说这取决于用例。用户是否总是必须通过这些元素?如果是这样,我可能倾向于在页面加载时抓取所有数据,或者甚至首先将数据与页面一起发送。

还取决于您处理的项目数量,也许自动完成是一个更好的解决方案。

确实需要一个更好的感觉,让应用程式更强烈建议

+0

好吧,我不想为所有国家获取所有数据......这可能是很多数据......它默认为加拿大,这是我们的目标受众......如果他们从未改变国家,那么其他国家的数据*永远不需要加载。将这个脚本用于更大的列表(过滤数千个元素)。自动完成并不合适,因为结果列表仍然会相对较小(少于50个选项)。 – mpen 2010-07-14 23:42:04

+0

“通过”?他总是选择一个省/州,是的。 (除非偶然违约是正确的) – mpen 2010-07-14 23:42:29