0

I m using google maps API to create markers on the map. I am creating a regular marker based on lat/lng. If that is missing, I am relying on the physical address and geocoding it. If I have more than 50 addresses, I am running into OVER_QUERY_LIMIT while geocoding. I have read few posts that suggested to use a timer. Where should I introduce a timer or a delay in such a scenario?

EDIT: Added a timer but doesn't work good. The browser snaps out after a while.

Here's my code:

$scope.loadMap = function(){
    $("#map").width(942).height(400);
    google.maps.event.trigger(map, "resize");
    var storeLatLng = new google.maps.LatLng(40.0000, -98.0000);
    var mapOptions = {
        zoom: 4,
        center: new google.maps.LatLng(40.0000, -98.0000),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    var bounds = new google.maps.LatLngBounds();
    if(!map){
        map = new google.maps.Map($('#map')[0], mapOptions);
    }
    else{
        map.setOptions(mapOptions);
    }   
    for (i = 0; i < $scope.addresses.length; i++) {
        var storeItem = $scope.addresses[i];

        if(storeItem.latitudeOrg && storeItem.longitudeOrg){
            $log.info("latlng for store:" + storeItem.city + ":" + storeItem.latitudeOrg +":"+storeItem.longitudeOrg);
            storeLatLng = new google.maps.LatLng(storeItem.latitudeOrg, storeItem.longitudeOrg);
            var marker1 = new google.maps.Marker({
                position: storeLatLng,
                map: map,
                title: storeItem.city
            });
        }
        else{ // Rely on physical address (city, state) if lat/lng is either empty or null
            var address = storeItem.address1 + "," + storeItem.city + "," + storeItem.state;
            $log.info("address for store:" +storeItem.id+":"+ ":" + address);
            var city = storeItem.city;
            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({
                'address' : address
            }, function(results, status) {
                if ( status == google.maps.GeocoderStatus.OK ) {
                    var locality='';
                    var lat = results[0].geometry.location.lat();
                    var lng = results[0].geometry.location.lng();
                    for(var i=0; i<results[0].address_components.length; i++){
                        var component = results[0].address_components[i];
                        if(component.types[0] == 'locality'){
                            locality = component.long_name; 
                        }
                    }
                    storeLatLng = new google.maps.LatLng(lat, lng);
                    var marker2 = new google.maps.Marker({
                        position: storeLatLng,
                        map: map,
                        title: locality.toUpperCase()
                    });

                } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                    $log.info("OVER_QUERY_LIMIT");
                    setTimeout(function() {
                        $scope.loadMarkers();
                    }, 100);
                } else {
                    $log.info("Geocode was not successful for the following reason:" + status);
                }
            });
        }
    }
}       
Mustang
  • 604
  • 2
  • 13
  • 32
  • Geocode them once and store results – charlietfl Mar 10 '16 at 20:05
  • Review the terms of use "The Google Maps Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited." – William Walseth Mar 10 '16 at 20:14
  • No caching or storage. You will not pre-fetch, cache, index, or store any Content to be used outside the Service, except that you may store limited amounts of Content solely for the purpose of improving the performance of your Maps API Implementation due to network latency (and not for the purpose of preventing Google from accurately tracking usage), and only if such storage: – William Walseth Mar 10 '16 at 20:15
  • https://developers.google.com/maps/terms#10-license-restrictions – William Walseth Mar 10 '16 at 20:15
  • @William - I am not sure what you are talking about? I am displaying the geocoded address on a map. – Mustang Mar 10 '16 at 20:20
  • You need a paid license if you're hitting the limit of the free API, and any attempt to prevent Google from tracking usage is a violation of their terms. – William Walseth Mar 10 '16 at 20:21
  • @WilliamWalseth there are many many resources for geocoding. Also storing geocodes is highly unlikely to be outside of terms and certainly there is no way for anyone to know how you geocoded them in the first place – charlietfl Mar 10 '16 at 20:27
  • @charlietfl - "storing geocodes is highly unlikely to be outside of terms " ... so why is there a whole section in their Terms about not storing geocoding results. I suggest you and your attorney re-read the terms. In particular section 10.5 D.. – William Walseth Mar 10 '16 at 20:32
  • If it's that concerting you use another service then to do the initial geocoding – charlietfl Mar 10 '16 at 20:33
  • @charlietfl - exactly, many other services are far less restrictive. I Recommend MapQuest as they have the least restrictive terms (I have no affiliation with MapQuest or Google) – William Walseth Mar 10 '16 at 20:35

1 Answers1

0

geocoder.geocode() works as asynchronous.

It means you request geocoder.geocode() 50 times at the same times. What happens in your code is:

geocoder.geocode()  ---> Send a geocode request to Google (#1)
geocoder.geocode()  ---> Send a geocode request to Google (#2)
geocoder.geocode()  ---> Send a geocode request to Google (#3)
geocoder.geocode()  ---> Send a geocode request to Google (#4)
geocoder.geocode()  ---> Send a geocode request to Google (#5)

<--- response from Google for #1
geocoder.geocode()  ---> Send a geocode request to Google (#6)
geocoder.geocode()  ---> Send a geocode request to Google (#7)
<--- response from Google for #2
geocoder.geocode()  ---> Send a geocode request to Google (#8)
geocoder.geocode()  ---> Send a geocode request to Google (#9)
<--- response from Google for #3
geocoder.geocode()  ---> Send a geocode request to Google (#10)
geocoder.geocode()  ---> Send a geocode request to Google (#11)
<--- response from Google for #4 "OVER_QUERY_LIMIT"  
<--- response from Google for #5 "OVER_QUERY_LIMIT"  
<--- response from Google for #6 "OVER_QUERY_LIMIT"  
<--- response from Google for #7 "OVER_QUERY_LIMIT"  
<--- response from Google for #8 "OVER_QUERY_LIMIT"  
<--- response from Google for #9 "OVER_QUERY_LIMIT"  
<--- response from Google for #10 "OVER_QUERY_LIMIT"  
<--- response from Google for #11 "OVER_QUERY_LIMIT"  

The problem in your code is here:

for (i = 0; i < $scope.addresses.length; i++) {
  ...
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode({
    'address' : address
  }, function(results, status) {
    ...
  });
}

You should wait until the before request.

var geocoder = new google.maps.Geocoder();
$scope.addresses
var looping = function(index) {

  var storeItem = $scope.addresses[index];
  var address = ...
  myGeocode(address, function(results, status) {
    ..
    index++;

    if (index < $scope.addresses.length) {
      looping(index, arguments.callee);
    }
  });
}
looping(0);

function myGeocode(address, callback) {
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode({
    'address' : address
  }, callback);
}
wf9a5m75
  • 6,100
  • 3
  • 25
  • 59