13

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>
4
  • Why are you geocoding the same address 20 times? Commented Feb 1, 2012 at 4:24
  • as an example. I noted that some API's suppliers (like google) don't like you to bang too frenquently on their doors. I would like to reduce the frequency of the call by using a timer, but am having trouble using it in a loop, Commented Feb 1, 2012 at 4:29
  • That's true, but why would you bang on their doors with the same request every time? Commented Feb 1, 2012 at 4:45
  • 3
    I wouldn't, but it would not add much to the question to include 20 (or 200 addresses). My question is more about delaying loops. Commented Feb 1, 2012 at 4:48

7 Answers 7

14

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?

Sign up to request clarification or add additional context in comments.

Comments

8

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.

Comments

6

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

}();

Comments

1

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

3 Comments

Pausing by using setTimeout/setInterval may all work for you, but it's an illusion. If I can read your code correctly, the original problem is that your loop is quicker than geocoder.geocode returns back each time. So, the only way to not have parallel geocode calls would be to wait until one is done before the next one is started. That said, there's no need to further slow down the loop - if all you were trying to avoid were parallel calls. If you still want to pause between calls, you should still use callbacks in combination with setTimeout.
Yes, I would like to avoid parallel calls as well as slowing down the loop. There seems to no way to make google api's to act synchronously so I have to stack everything into their sucess fuctions. I will try to understand your code...
the above eliminates parallel calls; to pause between calls, do this: if(counter < 20) { window.setTimeout(function(){ dogeo(geoCallback); } }, 2000);
1

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.