3

There's a query per second limit in Google Places API, so I need to slow down my loop which sends requests:

function callback(results, status) {
  if (status != google.maps.places.PlacesServiceStatus.OK) {
    alert(status);
    return;
  }
      for (var i = 0, result; result = results[i]; i++) {
    RequestInfo(result);
  }
}

Any idea how I can do that? I'm a bit of a newb.

PherricOxide
  • 15,493
  • 3
  • 28
  • 41
dlofrodloh
  • 1,728
  • 3
  • 23
  • 44

3 Answers3

4

Recursive solution,

function requestInfoWrapper(results, i) {
    i = i + 1;
    if (i >= results.length) {return};
    requestInfo(results[i]);
    setTimeout(function() {requestInfoWrapper(results, i);}, 1000);
}

Some example code to test it,

   var results = ["test 1", "test 2", "test 3"];
   function requestInfo(str) {console.log(str);}
   requestInfoWrapper(results, -1);

Also integrated with your code would just be,

function callback(results, status) {
    if (status != google.maps.places.PlacesServiceStatus.OK) {
        alert(status);
        return;
    }

    requestInfoWrapper(results, -1);
}
PherricOxide
  • 15,493
  • 3
  • 28
  • 41
  • @CrazyTrain: though that only works if `results` is global scope, and as long as `callback` isn't called before the last `setTimeout` occurs. ;-) – Brad Christie Aug 28 '13 at 20:27
  • Ok, but would the requestInfoWrapper function have access to the results array? Sorry I'm a bit of a newb. *edit* The results isn't global scope – dlofrodloh Aug 28 '13 at 20:32
  • @BradChristie: Yeah, I was commenting on the initial solution, which I assumed would have been placed inside the `callback` function. The last solution should modify `requestInfoWrapper` to pass in the `results` array. –  Aug 28 '13 at 20:35
  • Edited so results doesn't have to be global. – PherricOxide Aug 28 '13 at 20:54
2
for (var i = 0, result; result = results[i]; i++){
    (function(result){
        setTimeout(function(){
            RequestInfo(result);
        }, 1e3 * i);
    })(result);
}

You can use setTimeout and space them out to execute every 1 second * n (where n is the current iteration number).

And, for the more to the point answer, JavaScript doesn't have a "sleep" method (nor would you want it to; it's single threaded and would tie up anything else while it waited).

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • You've got the "callback in a loop" problem. –  Aug 28 '13 at 20:01
  • @CrazyTrain: admittedly I'm not familiar enough to maps api, nor do I know _exactly_ what `callback` is; I'm assuming you mean callback fires a bunch of `RequestInfo`'s which in turn recalls callback (lather, rinse, repeat)? – Brad Christie Aug 28 '13 at 20:03
  • 3
    Nothing specific to an api. It's just that the callback you're passing to `setTimeout` references the `result` variable, which is scoped to the enclosing function. Because the variable is overwritten in each iteration of the loop, when the callbacks are finally invoked, they'll be referencing the last value to which `result` was set, which will be `undefined`. –  Aug 28 '13 at 20:05
  • Hrm, that's not working for me. What's the 1e3 bit about? Should I change that to something else? – dlofrodloh Aug 28 '13 at 20:14
  • @CrazyTrain: Oh, duh. Heh, not thinking today. Should be fixed. ;-) **user**: 1e3 is just notation for 1 second (I find it easier than 1000). Case in point: 1/2 second = 0.5e3 (over 500), 1/4 = 0.25e3 (over 2500), etc. – Brad Christie Aug 28 '13 at 20:23
  • 1
    @user2721465: `1e3` is just a somewhat annoying way to spell `1000.0`. – cHao Aug 28 '13 at 20:24
1

You can use setTimeout to call the function recursively.

var i = 0;
function callback(results, status) {
  if (status != google.maps.places.PlacesServiceStatus.OK) {
    alert(status);
    return;
  }
  setTimeout(function() { 
    i++; 
    if (i < results.length) { 
      RequestInfo(results[i]);
      callback(results, status);
    }
  }, 1000);
}
Cole Pilegard
  • 582
  • 2
  • 11