使用Google Geocoder v3,如果我尝试对20个地址进行地理编码,除非得到的时间间隔为1秒左右,否则我将获得OVER_QUERY_LIMIT,但是所有标记都需要20秒才能放置完。
除了预先存储坐标外,还有其他方法吗?
使用Google Geocoder v3,如果我尝试对20个地址进行地理编码,除非得到的时间间隔为1秒左右,否则我将获得OVER_QUERY_LIMIT,但是所有标记都需要20秒才能放置完。
除了预先存储坐标外,还有其他方法吗?
Answers:
不,实际上没有其他方法:如果您有很多位置并希望在地图上显示它们,则最佳解决方案是:
当然,这是考虑到与位置咨询相比,您对位置的创建/修改要少得多。
是的,这意味着您在保存位置时必须做更多的工作-但这还意味着:
实际上,您不必为每个请求都等待一秒钟。我发现,如果我在每个请求之间等待200毫秒,就可以避免OVER_QUERY_LIMIT响应,并且用户体验是可以通过的。使用此解决方案,您可以在4秒钟内加载20个项目。
$(items).each(function(i, item){
setTimeout(function(){
geoLocate("my address", function(myLatlng){
...
});
}, 200 * i);
}
setInterval
对所需的请求数量进行处理,而不是setTimeout
对它进行设置,并将其设置为100
-以防万一地址数量将来会扩展20
。
不幸的是,这是对Google地图服务的限制。
我目前正在使用地理编码功能开发应用程序,并且正在按用户保存每个唯一地址。我根据Google地图返回的信息生成地址信息(城市,街道,州等),然后将纬度/经度信息也保存在数据库中。这样可以避免您必须重新编码内容,并为您提供格式正确的地址。
您要执行此操作的另一个原因是,每天对可以从特定IP地址进行地址解析的地址数量有限制。您不希望因此而导致应用程序失败。
编辑:
忘了说这个解决方案是在纯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);
}
});
}
};
请注意,这只是我为处理Google Maps编写的更大的图书馆的一部分,因此评论可能会令人困惑。
用法很简单,但是方法略有不同:您不需要一次循环并解析一个地址,而是需要将一个地址数组传递给该类,并且它将自行处理搜索,并返回一个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。
希望这可以在不久的将来对某人有所帮助;)
我刚刚测试了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
}
}
希望能帮助到你