【问题标题】:how to slow down a javascript loop如何减慢javascript循环
【发布时间】:2012-02-01 04:21:22
【问题描述】:

我想在以下循环的每次迭代中添加 1-2 秒的延迟。

<html>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<input id="start" type="submit"> </input>
<div id='status'></div>

<script>
var geocoder=new google.maps.Geocoder();                   
var glGeocodeCount = 0 ;

$(document).ready(function() {

    $('#start').click(function() {

        //srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");      

        for(x=0;x<20;x++){
            srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");
        }
        return false;
    });          
}); 

function srPerformGeocode(address){     
    if (geocoder){                
        geocoder.geocode({ 'address': address }, function (results, status) {                                                                              
            if (status == google.maps.GeocoderStatus.OK){                                                                                                                                                                           
                $('#status').prepend("Success : " + address + "<br/>");

            }
            else{
                $('#status').prepend("Failed : " + address + "<br/>");

            }
        });
    }
}
</script>

【问题讨论】:

  • 为什么要对同一个地址进行 20 次地理编码?
  • 为例。我注意到一些 API 的供应商(如谷歌)不喜欢你过于频繁地敲门。我想通过使用计时器来减少通话频率,但在循环中使用它时遇到问题,
  • 没错,但你为什么每次都用同样的要求敲门呢?
  • 我不会,但包含 20 个(或 200 个地址)不会对问题增加太多。我的问题更多是关于延迟循环。

标签: javascript loops


【解决方案1】:

您可以通过setTimeout() 做到这一点:

$(document).ready(function() {
    $('#start').click(function() {
        //srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");      
        var x = 0;

        function go() {
            srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");
            if (x++ < 20) {
                setTimeout(go, 2000);
            }
        }
        go();

        return false;
    });          
}); 

这确实让我想知道为什么您要连续 20 次对完全相同的地址进行地理编码查找?

【讨论】:

    【解决方案2】:

    您可能想为此使用计时器。如果只是在代码中放一个延迟循环,结果只会是代码运行时间更长,但最终结果会在代码完成后立即显示出来。

    您可以使用 setTimeout 或 setInterval 方法。示例:

    function(){
    
    var instructions = [
    function() { /* do something */ },
    function() { /* do something */ },
    function() { /* do something */ },
    function() { /* do something */ }
    ];
    
    var index = 0;
    
    var handle = window.setInterval(function() {
    if (index < instructions.length) {
      instructions[index++]();
    } else {
      window.clearInterval(handle);
    }
    }, 10);
    
    }();
    

    【讨论】:

      【解决方案3】:

      现代 JS 解决方案:

      function timeout(ms) {
          return new Promise(resolve => setTimeout(resolve, ms))
      }
      
      async function slowedCode() {
          console.log("Before Delay")
          await this.timeout(Math.random() * 2000 + 500) // Wait random amount of time between [0.5, 2.5] seconds
          console.log("After Delay")
      }
      
      async function slowedForLoop() {
          const data = ["1","2","3","4","5"]
          for (let d of data) {
              console.log(d)
              await this.timeout(Math.random() * 100 + 500)
          }    
      }
      

      唯一的缺点是您必须从异步函数内部执行延迟。

      【讨论】:

        【解决方案4】:

        我有一种感觉,在地理编码查找真正完成之前,您不希望开始下一次循环迭代。所以,这里的关键字是“回调”:

        请执行以下操作,而不是 for...。我知道这可能不是你习惯的东西,但请尝试掌握它(它应该有效)。

        var dogeo = function(callback)
        {
            srPerformGeocode("address", callback);
        };
        
        var counter = 0;
        
        var geoCallback = function()
        {
                 counter++;
        
                 if(counter < 20)
                 {
                     dogeo(geoCallback);
                 }
        
        };
        
        
        dogeo(geoCallback);
        
        
        
        function srPerformGeocode(address, callback){     
            if (geocoder){                
                geocoder.geocode({ 'address': address }, function (results, status) {    
        
        
                   // this function is a callback of geocode()
        
                    if (status == google.maps.GeocoderStatus.OK){                                                                                                                                                                           
                        $('#status').prepend("Success : " + address + "<br/>");
        
                    }
                    else{
                        $('#status').prepend("Failed : " + address + "<br/>");
        
                    }
        
                    callback(); // let the caller know this is done
                });
            }
        }
        

        【讨论】:

        • 使用 setTimeout/setInterval 暂停可能对你有用,但这是一种错觉。如果我能正确阅读您的代码,那么最初的问题是您的循环比 geocoder.geocode 每次返回的速度都要快。因此,没有并行地理编码调用的唯一方法是等到一个完成后再开始下一个。也就是说,没有必要进一步减慢循环 - 如果您试图避免的只是并行调用。如果您仍想在调用之间暂停,您仍应结合 setTimeout 使用回调。
        • 是的,我想避免并行调用以及减慢循环速度。似乎没有办法让谷歌 api 同步行动,所以我必须把所有东西都堆叠到他们的成功功能中。我会试着理解你的代码...
        • 以上消除了并行调用;要在通话之间暂停,请执行以下操作:if(counter &lt; 20) { window.setTimeout(function(){ dogeo(geoCallback); } }, 2000);
        【解决方案5】:

        我最终为此使用了模数运算符。然后你可以增加/减少它除以增加/减少延迟时间的量。不过,如果没有 for 循环可能会更好。

        $(document).ready(function() {
        
            $('#start').click(function() {
              
                var delay = 0;
                for(x=0;x<20;x){
                    delay++;
                    if (delay % 10 == 0) {
                        srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");
                        x++;
                    }
                }
                return false;
            });          
        }); 
        

        【讨论】:

          【解决方案6】:

          我鼓励摆脱循环并使用 setTimeout:

              $('#start').click(function() {
                  var i = 0, max = 20, delay = 2000, run;
                  run = function(){
                     srPerformGeocode("TD Tower, 55 King Street West, Toronto, ON, Canada, M5K 1A2");
                     if(i++ < max){
                        setTimeout(run, delay);
                     }
                  }
                  run();
                  return false;
              });
          

          【讨论】:

            猜你喜欢
            • 2017-06-29
            • 2021-04-23
            • 1970-01-01
            • 2022-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-06-20
            相关资源
            最近更新 更多