Mustapha George
Mustapha George

Reputation: 2527

how to slow down a javascript loop

I would like a add a 1-2 second delay on each iteration of the following loop.

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

Upvotes: 13

Views: 36800

Answers (7)

Mariusz Mleczko
Mariusz Mleczko

Reputation: 21

Probably the simplest way is to call a setTimeout loop with a variable increasing delay for each loop iteration...

for (var i = 0; i < max_val; ++i) {
    setTimeout(doSomething, (milisecond_delay * i), param1, param2, param3, ...);
}

Upvotes: 0

E.T. Deubner
E.T. Deubner

Reputation: 11

I ended up using the modulus operator for this purpose. Then you can increase/decrease the amount it divides by to increase/decrease the delay time. Would probably be better without the for loop though.

$(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;
    });          
}); 

Upvotes: 1

Neal Soni
Neal Soni

Reputation: 704

Modern JS Solution:

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

The only draw back is you have to execute the delay from inside an async function.

Upvotes: 8

user191966
user191966

Reputation:

I have a feeling you'd rather not to start next loop iteration until the geocode lookup is truly complete. So, the keyword there is "callback":

instead of the for..., do the below. I know it may not be something you're used to, but please try to grasp it (it should work).

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

Upvotes: 1

driangle
driangle

Reputation: 11779

I encourage getting rid of the loop and using 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;
    });

Upvotes: 0

jfriend00
jfriend00

Reputation: 707696

You can do it this way with 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;
    });          
}); 

This does make me wonder why you're doing a geocode lookup on the exact same address 20 times in a row?

Upvotes: 14

user1181888
user1181888

Reputation:

You probably want to use a timer for this. If you would just put a delay loop in the code, the result would only be that the code takes longer to run, but the final result will show up all at once after the code has finished.

You can use the setTimeout or setInterval methods. Example:

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

}();

Upvotes: 6

Related Questions