Search code examples
javascriptgoogle-mapspromisegoogle-geocoder

Synchronous Javascript Promise with timeouts to overtime Google Geocode querylimit


I have a list of >100 addresses and am trying to make requests to Geocoder to get the latitude and longitude. After I have all the resulting lat/longs, I will call a callback to do something with it. Google's geocoding API has a time limit on the requests per second, so I would like to set a 1 sec delay in between each request. I have the code below using Javascript Promise which calls Geocoder API, but it looks like the timeouts all happen at the same time. Is there a way to make the timeouts happen sequentially using Promises?

function geoCodePromise(address) {
  let promise = new Promise(function(resolve, reject) {

    geocoder.geocode({
      'address': address
    }, function(res, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        setTimeout(function() { resolve(res[0].geometry.location); }, 1000);
      } else {
        setTimeout(function() { reject(status); }, 1000);
      }
    });
  });

  return promise;
}

// long list of addresses. Listing two here for example
let addresses = ["1340 Lincoln Blvd, Santa Monica, CA 90401", "223 N 7th Ave, Phoenix, AZ 85007"]

let promises = [];
for (let i=1; i < addresses.length; i++) {
  promises.push(geoCodePromise(addresses[i]));
}

Promise.all(promises).then(function(results) {
  // callback to do something with the results
  callbackfunc(results)
})
.catch(function(err) {
  console.log(err);
})

Solution

  • Try passing i to geoCodePromise to multiply by 1000 at setTimeout duration; removing setTimeout at reject; calling geoCodePromise at for loop

    function geoCodePromise(address, i) {
      let promise = new Promise(function(resolve, reject) {   
        geocoder.geocode({
          'address': address
        }, function(res, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            setTimeout(function() { resolve(res[0].geometry.location); }, 1000 * i);
          } else {
            reject(status);;
          }
        });
      });   
      return promise;
    }
    
    // long list of addresses. Listing two here for example
    let addresses = ["1340 Lincoln Blvd, Santa Monica, CA 90401", "223 N 7th Ave, Phoenix, AZ 85007"]
    
    let promises = [];
    for (let i = 1; i < addresses.length; i++) {
      promises.push(geoCodePromise(addresses[i], i));
    }
    
    Promise.all(promises).then(function(results) {
      // callback to do something with the results
      callbackfunc(results)
    })
    .catch(function(err) {
      console.log(err);
    })
    

    function geoCodePromise(a, i) {
      let promise = new Promise(function(resolve) {
        setTimeout(function() {
          resolve([a, i])
        }, 1000 * i)
      })
      return promise
    }
    let addresses = "abcdefg".split("");
    let promises = [];
    
    for (let i = 0; i < addresses.length; i++) {
      promises.push(geoCodePromise(addresses[i], i));
    }
    
    Promise.all(promises).then(function(results) {
      // callback to do something with the results
      callbackfunc(results)
    })
    .catch(function(err) {
      console.log(err);
    });
    
    function callbackfunc(results) {
      console.log(JSON.stringify(results, null, 2))
    }