Reputation: 601
I've been struggling through this for a few days now - I've got it working how I want but then I keep running into roadblocks which I will describe below. It's got to the point where I just need to ask for some advice from someone who has the necessary experience.
So this is what I ultimately want to achieve:
Pretty simple in terms of functionality really.
I originally was using the Google Maps JavaScript API together with the Google Places API JavaScript Library.
I got the basic functionality working, but ran into the OVER_QUERY_LIMIT
problem.
I discovered this happens because of the simultaneous requests being made (nothing to do with the daily usage limits); for example when the user clicks "Walmart", trying to show ~10+ stores on the map at the same time is blocked by Google.
From my research, it looked like I'd have to use the Google Maps API Web Services instead.
If too many requests are made within a certain time period, the API returns an OVER_QUERY_LIMIT response code. The per-session rate limit prevents the use of client-side services for batch requests. For batch requests, use the Maps API web services.
So I also got it all working for a 2nd time using the Google Places API Web Service which I was pretty pleased about. I'm using AJAX to request the JSON from Google, but now I get the following console error:
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=53.000403,-1.129625&radius=10000&name=Sainsbury's|Debenhams&key=API_KEY. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I know I'm getting this error because I'm requesting from a different server/domain. Here's my code, which I'm just running locally at the moment:
accessURL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="+userCords.latitude+","+userCords.longitude+"&radius=10000&name=Sainsbury's|Debenhams&key=API_KEY";
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: accessURL,
dataType: 'json',
success: function (data) {
$.each(data.results, function (i, val) {
storeId.push(val.place_id);
storeName.push(val.name);
});
//Now, use the id to get detailed info
$.each(storeId, function (k, v){
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "https://maps.googleapis.com/maps/api/place/details/json?placeid="+v+"&key=API_KEY",
dataType: 'json',
success: function (data) {
var latitude = data.result.geometry.location.lat;
var longitude = data.result.geometry.location.lng;
//set the markers.
myLatlng = new google.maps.LatLng(latitude,longitude);
allMarkers = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.result.name,
html: '<div class="marker-content">' +
'<p>'+data.result.name+'</p>' +
'<p>'+data.result.formatted_address+'</p>' +
'</div>'
});
//put all lat long in array
allLatlng.push(myLatlng);
//Put the markers in an array
tempMarkerHolder.push(allMarkers);
google.maps.event.addListener(allMarkers, 'click', function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
// Make an array of the LatLng's of the markers you want to show
// Create a new viewpoint bound
var bounds = new google.maps.LatLngBounds ();
// Go through each...
for (var i = 0, LtLgLen = allLatlng.length; i < LtLgLen; i++) {
// And increase the bounds to take this point
bounds.extend (allLatlng[i]);
}
// Fit these bounds to the map
map.fitBounds (bounds);
}
});
}); //end .each
}
});
For testing, I've used this https://crossorigin.me prepended onto the API access urls to temporarily get around this issue, but now I actually need to solve the problem properly.
After some research, I saw a lot of people advising to change the dataType
to jsonp
. But when I do that, I get the following console error:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=53.041981899999996,-1.1898794&radius=10000&name=Sainsbury%27s|Debenhams&key=API_KEY&callback=jQuery111309486707670378429_1491079656734&_=1491079656735:2 Uncaught SyntaxError: Unexpected token :
After even more research into that latest error, I'm seeing things like "looks like the places api doesn't support ajax or jsonp", which is extremely annoying after I got it all working already!
Then I saw this:
The Google Places API Web Service is for use in server applications. If you're building a client-side application, take a look at the Google Places API for Android and the Places Library in the Google Maps JavaScript API.
Which means I've now gone full circle!
I'm at the point where I guess I have to work out a server-side solution instead of a client-side one. But honestly, I have no idea where to go from here and can't find anything online to point me in the right direction.
Can anyone please advise what to do next? What would a "server-side solution" look like? I've come this far, I really don't want to quit now! Any help would be hugely appreciated!
Upvotes: 1
Views: 4423
Reputation: 75
I got the same OVER_QUERY_LIMIT message about sending 90 requests, Here is some solutions sort out from the stackOverFlow:
so I try to delay my requets, this can not prevent OVER_QUERY_LIMIT ,but will greatly reduce frequency.Here is my core function about google map api direction, just like your google map place Api.
function calculateDirections( directionsService, requestList, responseList, deferred, recursiveCount ) {
var deferred = deferred || $q.defer();
var responseList = responseList || [];
var recursiveCount = recursiveCount || 0;
var directionRequest = {
origin: requestList[ recursiveCount ].origin,
destination: requestList[ recursiveCount ].destination,
waypoints: requestList[ recursiveCount ].waypoints,
optimizeWaypoints: false,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route( directionRequest, function ( response, status ) {
if ( status === google.maps.DirectionsStatus.OK ) {
responseList.push( response );
if ( requests.length > 0 ) {
//delay google request,millisecond
setTimeout( function () {
recursiveCount++;
calculateDirections( directionsService, requests, responseList, deferred, recursiveCount );
}, recursiveCount * 10 + 500 );
} else {
deferred.resolve( responseList );
}
}else if( status === google.maps.DirectionsStatus.OVER_QUERY_LIMIT ){
//try again google request
setTimeout( function () {
calculateDirections( directionsService, requests, responseList, deferred, recursiveCount );
}, recursiveCount * 10 + 500 );
} else {
var result = {};
result.status = status;
deferred.reject( result );
}
} );
return deferred.promise;
}
Upvotes: 0
Reputation: 32178
To solve the issue you should build your own intermediate server that will send requests to Google (server side requests) and pass the JSON responses back to your client side application. In other words you should build a proxy to avoid the CORS issue.
How you build the proxy server, it's completely up to you. Choose the technology you are familiar with (Java, Python, NodeJs, etc.) and implement a server side code.
The client side code will send requests to intermediate server, intermediate server will send HTTPS request to Google and pass the response back to client side.
There are several useful libraries on GitHub that you can use server side with NodeJs, Java, Python or Go:
https://github.com/googlemaps/google-maps-services-js
https://github.com/googlemaps/google-maps-services-java
https://github.com/googlemaps/google-maps-services-python
https://github.com/googlemaps/google-maps-services-go
Hope it helps!
Upvotes: 0