【问题标题】:A more graceful way of throttling jQuery $().each?一种更优雅的 jQuery $().each 节流方式?
【发布时间】:2015-08-28 00:19:12
【问题描述】:

我正在尝试通过输入使用 jQuery 来 $().each,基于其中两个输入进行 AJAX 调用并更新第三个输入。但是,AJAX 调用(谷歌地图反向地理编码)有调用限制,这意味着我必须限制每秒发出的请求数。

我试图通过调用 setTimeout 来限制 each,每次迭代的超时时间增加 2 秒,但它只是一次调用它们。关于我做错了什么的任何见解?我的方法基于this question 但是 有几件事——特别是元素会随着每次迭代而变化——使这变得更加复杂。

<button class="identify-locations">Identify locations</button>

<div class="row">
    <input class="address"></input>
    <input class="lat"></input>
    <input class="lng"></input>
</div>
<!-- the same thing over again 30 times -->

<script>
    $(".identify-locations").click(function(event){
        var time = 2000;
        $(".row").each(function(){
            if($(this).find(".lat").val() == '' && $(this).find(".lng").val() == ''){
                setTimeout( geocodeLocation($(this)), time);
                time += 2000;
            }
        });
    });

    function geocodeLocation(object, time){
        address = object.find(".address").val();
        var geocoder = new google.maps.Geocoder();
        geocoder.geocode({address: address},
            function(results_array, status) {
                if(status == 'OK'){
                    object.find(".lat").val( parseFloat(results_array[0].geometry.location.lat()) ); 
                    object.find(".lng").val( parseFloat(results_array[0].geometry.location.lng()) );
                    updateCount();
                }
        });
    }

</script>

【问题讨论】:

    标签: javascript jquery ajax


    【解决方案1】:

    您正在使用一个立即返回结果的函数调用 setTimeout。

    改为

    if($(this).find(".lat").val() == '' && $(this).find(".lng").val() == ''){
     var $current = $(this);
     setTimeout(function() { geocodeLocation($current)}, time);
     time += 2000;
    }
    

    也可以查看Passing parameters into a closure for setTimeout

    请注意,有用的 .bind 在 IE8/Safari5 中不可用

    【讨论】:

      【解决方案2】:

      问题是您在以下位置调用函数 geocodeLocation:

      setTimeout( geocodeLocation($(this)), time);
      

      相反,您应该只指向其标签。因此,应该是:

      setTimeout( geocodeLocation.bind(null, $(this)), time);
      

      【讨论】:

        【解决方案3】:

        尝试使用index.each()

         var time = 2000;
         $(".row").each(function(index){
           if($(this).find(".lat").val() == '' 
              && $(this).find(".lng").val() == '') {
                setTimeout(function() { 
                  geocodeLocation($(this))
                }.bind(this), index * time);                    
           }
         });
        

        【讨论】:

        • 嗯,从未见过这种结构。看起来很有趣。我想知道为什么我在控制台中看到一个数字对象而不是原始对象...我将尝试使用 jQuery 集合来实现这一点——这很有效。太棒了-jsfiddle.net/mplungjan/36d7b2ar
        • 啊哈:IE8 和 Safari5 不支持绑定
        • 不确定。我现在不在电脑上
        猜你喜欢
        • 1970-01-01
        • 2012-01-26
        • 1970-01-01
        • 2016-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多