Reputation: 179
I'am using Google Maps API to display a list of 20 locations and the time to get there. I am using google.maps.DirectionsService. This API has a limit per second set to 10 calls, if I have just 10 location I can call all at the same time(Tested and it works perfectly). When I have more than 10 location I'm calling using call blocks. For example with 16 locations: I call for the first 10 locations, then I wait 3 seconds and call for the others 6.
Theoretically, this approach supposed to work, because I'm respecting the restriction of 10 per second. BUT, doesn't work. I'm getting the error, OVER_QUERY_LIMIT when I try to call for the remaining 6 locations, sometimes four of them fail, sometimes 3 of them fail. If I increase the waiting time to 5 seconds, sometimes work ok, sometimes one of them fail.
Question: Isn't this limit supposed to be 10 queries per second? If yes, then what could I be doing wrong? and How I can fix it?
//------------------ Code ----------------
getDistanceByBlocks(destinations: IDestination[]){
let limit = 8;
if(destinations.length <= limit){
destinations.forEach(destination => {
this.getDistance(destination);
});
}else{
let selection = destinations.slice(0, limit)
let rest = destinations.slice(limit)
selection.forEach(destination => {
this.getDistance(destination);
});
setTimeout(() => {
this.getDistanceByBlocks(rest)
},3000);
}
}
getDistance(destination: IDestination) {
if (this.dataService.getCurrentLocation()) {
let mapSettings = this.userSettings.getMapSettingsSync();
this.mapService.getRoutes(destination, mapSettings);
}
}
//------------------ MapService----------------
getRoutes(destination: IDestination, mapSettings:IMapSettings): void {
let directionsService = new google.maps.DirectionsService;
this.currentLocation = this.dataService.getCurrentLocation();
directionsService.route(
{
origin: { lat: this.currentLocation.latitude,
lng: this.currentLocation.longitude },
destination: { lat: destination.latitude, lng: destination.longitude },
provideRouteAlternatives: mapSettings.provideRouteAlternatives,
avoidHighways: mapSettings.avoidHighways,
avoidTolls: mapSettings.avoidTolls,
drivingOptions: {
departureTime: new Date(Date.now()),
trafficModel: mapSettings.trafficModel
},
travelMode: google.maps.DirectionsTravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL
},
(response, status) => {
if (status == google.maps.DirectionsStatus.OK) {
let routes: IRouteInfo[] = response.routes
.map(route => {
let routeInfo: IRouteInfo = {
summary: route.summary,
distance: route.legs[0].distance.text,
timeValue: route.legs[0].duration.text,
};
return routeInfo;
});
destination.routes = routes;
this.events.publish(AppSettings.UPDATE_DESTINATIONS)
} else if (status == google.maps.DirectionsStatus.OVER_QUERY_LIMIT){
console.warn(status);
} else {
console.warn(status);
}
});
}
It is important to note that in Chrome network tab we can see the waiting time between each call and how many errors I am experiencing. What intrigues me a lot is that I do not see the failed calls, chrome does not show them to me. So I think that google.maps service is handling it in javascript and it is not making the calls to the server, but really I have not clue.
Upvotes: 1
Views: 2044
Reputation: 1849
I had the same problem in one of my project. I think you have to keep a time between each request. Like this, the server is continually charged. For my project, I use this code:
for (var i = 0; i<6; i++) {
(function (i) {
setTimeout(function () {
var service = new google.maps.places.PlacesService(map);
var request = {
placeId: yourArray [i]
};
service.getDetails(request, callback);
}, i * 300);
})(i);
}
Here, I define the request and I send it. Notice that I give a time of 0.3 sec between each request.
And you can also use this code in order to know when you have the OVER_QUERY_LIMIT error:
function callback (place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
...
} else if (status != google.maps.places.PlacesServiceStatus.OK && status != google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
console.error("Fail get detail try to rerequest.:(");
...
// For specials errors.
} else if (status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
console.error("Over Query Limit");
retry ();
}
}
Tell me if you have some questions or some comments.
Upvotes: 1