AMore
AMore

Reputation: 179

Google Maps API - OVER QUERY LIMIT per second limit

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.

Chrome Network Tab Example

Upvotes: 1

Views: 2044

Answers (1)

SphynxTech
SphynxTech

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

Related Questions