我如何在没有收到OVER_QUERY_LIMIT响应的情况下对地址parsing20个地址?

使用Google Geocoder v3,如果我试图对20个地址进行地址parsing,我会得到一个OVER_QUERY_LIMIT,除非我把它们分开的时间大约为1秒,但是在放置标记之前需要20秒。

除了预先存储坐标之外,还有其他的方法吗?

不,没有其他的办法:如果你有很多地点,想要在地图上显示,最好的解决办法是:

  • 在创build位置时使用地理编码器获取纬度+经度
  • 将这些数据存储在您的数据库中,并附上地址
  • 并在要显示地图时使用存储的纬度+经度。

当然,这是考虑到你的位置创build/修改的次数远远less于你对位置的咨询。

是的,这意味着您在保存位置时不得不做更多的工作 – 但这也意味着:

  • 您将可以按地理坐标进行search
    • 即“ 我想要一个靠近我现在位置的点的列表
  • 显示地图会快很多
    • 即使有超过20个位置
  • 哦,还(最后但并非最不重要) :这将工作;-)
    • 您将不太可能在N秒内达到X地理编码器呼叫的限制。
    • 而且你每天都不太可能达到Y地理编码器的限制。

您实际上不必为每个请求等待一秒钟。 我发现,如果在每个请求之间等待200毫秒,我可以避免OVER_QUERY_LIMIT响应,用户体验也是可以通过的。 有了这个解决scheme,您可以在4秒内加载20个项目。

$(items).each(function(i, item){ setTimeout(function(){ geoLocate("my address", function(myLatlng){ ... }); }, 200 * i); } 

不幸的是,这是Google地图服务的限制。

我目前正在使用地理编码function的应用程序,我保存每个用户的每个唯一的地址。 我根据Google地图返回的信息生成地址信息(城市,街道,州等),然后将经纬度信息保存在数据库中。 这可以防止你不得不重新编码的东西,并给你很好的格式化地址。

您想要这样做的另一个原因是,可以从特定IP地址进行地理编码的地址数量每天都有限制。 出于这个原因,你不希望你的申请失败。

我正在尝试对地址进行地址parsing时遇到同样的问题。

我的解决方法是为每个循环的下一个地理编码请求添加usleep(100000) 。 如果请求的状态是OVER_QUERY_LIMIT,那么就会增加50000,然后重复请求,依此类推。

并且导致所有接收到的数据(lat / long)都存储在XML文件中,每次页面加载时都不会运行请求。

编辑:

忘了说这个解决scheme是纯js的,你唯一需要的是支持promise的浏览器https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise


对于那些仍然需要完成这些的人来说,我写了自己的解决scheme,将承诺和超时结合在一起。

码:

 /* 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); } }); } }; 

请注意,这只是我写的一个更大的图书馆的一部分来处理谷歌地图的东西,因此评论可能会令人困惑。

用法很简单,但是这种方法略有不同:不是一次循环和parsing一个地址,而是需要将一个地址数组传递给类,它将自己处理search,返回一个promise ,parsing后返回一个包含所有已parsing(和未parsing)地址的数组。

例:

 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毫秒地址被控制。

我做了一些进一步的testing,我发现,即使在700毫秒,我有时得到QUERY_LIMIT错误,而与750我没有任何问题。

在任何情况下,如果您觉得通过处理较低的延迟而感到安全,请随时编辑上面的750。

希望这可以帮助不久的将来;)

我刚刚testing了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 } } 

希望它有帮助