使用谷歌地理编码器v3,如果我尝试对20个地址进行地理编码,我会得到一个OVER_QUERY_LIMIT,除非我将它们分开约1秒,但是我的标记全部放置需要20秒。
除了预先存储坐标之外,还有其他办法吗?
答案 0 :(得分:83)
不,没有其他任何方式:如果你有很多地方并希望在地图上显示它们,最好的解决方案是:
当然,考虑到您创建/修改地点的次数比您在地点协商方面少得多。
是的,这意味着在保存位置时你将不得不做更多的工作 - 但这也意味着:
答案 1 :(得分:20)
实际上,您不必为每个请求等待一整秒。我发现如果我在每个请求之间等待200毫秒,我就可以避免OVER_QUERY_LIMIT响应并且用户体验可以通过。使用此解决方案,您可以在4秒内加载20个项目。
$(items).each(function(i, item){
setTimeout(function(){
geoLocate("my address", function(myLatlng){
...
});
}, 200 * i);
}
答案 2 :(得分:6)
不幸的是,这是Google地图服务的限制。
我目前正在使用地理编码功能处理应用程序,并且我将基于每个用户保存每个唯一地址。我根据谷歌地图返回的信息生成地址信息(城市,街道,州等),然后将纬度/经度信息保存在数据库中。这可以防止您不得不重新编码,并为您提供格式良好的地址。
您想要执行此操作的另一个原因是,可以从特定IP地址进行地理编码的地址数量每日限制。出于这个原因,您不希望您的应用程序因某个人而失败。
答案 3 :(得分:2)
我在尝试对140个地址进行地理编码时面临同样的问题。
我的解决方法是为下一个地理编码请求的每个循环添加 usleep(100000)。如果请求的状态为OVER_QUERY_LIMIT,则usleep将增加50000并重复请求,依此类推。
因为所有收到的数据(纬度/经度)都存储在XML文件中,不会在每次加载页面时都运行请求。
答案 4 :(得分:1)
编辑:
忘了说这个解决方案是纯粹的js,你唯一需要的是一个支持承诺的浏览器 https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise
对于那些仍然需要完成此任务的人,我已经编写了自己的解决方案,将承诺与超时结合起来。
代码:
/*
class: Geolocalizer
- Handles location triangulation and calculations.
-- Returns various prototypes to fetch position from strings or coords or dragons or whatever.
*/
var Geolocalizer = function () {
this.queue = []; // queue handler..
this.resolved = [];
this.geolocalizer = new google.maps.Geocoder();
};
Geolocalizer.prototype = {
/*
@fn: Localize
@scope: resolve single or multiple queued requests.
@params: <array> needles
@returns: <deferred> object
*/
Localize: function ( needles ) {
var that = this;
// Enqueue the needles.
for ( var i = 0; i < needles.length; i++ ) {
this.queue.push(needles[i]);
}
// return a promise and resolve it after every element have been fetched (either with success or failure), then reset the queue.
return new Promise (
function (resolve, reject) {
that.resolveQueueElements().then(function(resolved){
resolve(resolved);
that.queue = [];
that.resolved = [];
});
}
);
},
/*
@fn: resolveQueueElements
@scope: resolve queue elements.
@returns: <deferred> object (promise)
*/
resolveQueueElements: function (callback) {
var that = this;
return new Promise(
function(resolve, reject) {
// Loop the queue and resolve each element.
// Prevent QUERY_LIMIT by delaying actions by one second.
(function loopWithDelay(such, queue, i){
console.log("Attempting the resolution of " +queue[i-1]);
setTimeout(function(){
such.find(queue[i-1], function(res){
such.resolved.push(res);
});
if (--i) {
loopWithDelay(such,queue,i);
}
}, 1000);
})(that, that.queue, that.queue.length);
// Check every second if the queue has been cleared.
var it = setInterval(function(){
if (that.queue.length == that.resolved.length) {
resolve(that.resolved);
clearInterval(it);
}
}, 1000);
}
);
},
/*
@fn: find
@scope: resolve an address from string
@params: <string> s, <fn> Callback
*/
find: function (s, callback) {
this.geolocalizer.geocode({
"address": s
}, function(res, status){
if (status == google.maps.GeocoderStatus.OK) {
var r = {
originalString: s,
lat: res[0].geometry.location.lat(),
lng: res[0].geometry.location.lng()
};
callback(r);
}
else {
callback(undefined);
console.log(status);
console.log("could not locate " + s);
}
});
}
};
请注意,它只是我为处理谷歌地图而编写的更大图书馆的一部分,因此评论可能会令人困惑。
用法非常简单,但是,方法略有不同:您不需要一次循环和解析一个地址,而是需要将一个地址数组传递给类,它将自己处理搜索,返回一个promise,当被解析时,返回一个包含所有已解析(和未解析)地址的数组。
示例:
var myAmazingGeo = new Geolocalizer();
var locations = ["Italy","California","Dragons are thugs...","China","Georgia"];
myAmazingGeo.Localize(locations).then(function(res){
console.log(res);
});
控制台输出:
Attempting the resolution of Georgia
Attempting the resolution of China
Attempting the resolution of Dragons are thugs...
Attempting the resolution of California
ZERO_RESULTS
could not locate Dragons are thugs...
Attempting the resolution of Italy
返回对象:
整个魔法发生在这里:
(function loopWithDelay(such, queue, i){
console.log("Attempting the resolution of " +queue[i-1]);
setTimeout(function(){
such.find(queue[i-1], function(res){
such.resolved.push(res);
});
if (--i) {
loopWithDelay(such,queue,i);
}
}, 750);
})(that, that.queue, that.queue.length);
基本上,它在每个项目之间循环延迟750毫秒,因此每750毫秒一个地址被控制。
我已经做了一些进一步的测试,我发现即使在700毫秒我有时也会收到QUERY_LIMIT错误,而在750时我根本没有任何问题。
在任何情况下,如果您觉得自己的安全性较低,请随时编辑上述750.
希望这可以在不久的将来帮助某人;)
答案 5 :(得分:0)
我刚刚测试了Google Geocoder并遇到了与您相同的问题。 我注意到我每12次请求只获得一次OVER_QUERY_LIMIT状态 所以我等了1秒(这是等待的最小延迟) 它会减慢应用程序的速度,但每次请求都会等待1秒
info = getInfos(getLatLng(code)); //In here I call Google API
record(code, info);
generated++;
if(generated%interval == 0) {
holdOn(delay); // Every x requests, I sleep for 1 second
}
使用基本的holdOn方法:
private void holdOn(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException ex) {
// ignore
}
}
希望有所帮助