Google Geocoder v3を使用して、20個のアドレスをジオコーディングしようとすると、1秒間隔で配置しない限り、OVER_QUERY_LIMITが発生しますが、マーカーがすべて配置されるまでに20秒かかります。
事前に座標を保存する以外に、他に方法はありますか?
Google Geocoder v3を使用して、20個のアドレスをジオコーディングしようとすると、1秒間隔で配置しない限り、OVER_QUERY_LIMITが発生しますが、マーカーがすべて配置されるまでに20秒かかります。
事前に座標を保存する以外に、他に方法はありますか?
回答:
いいえ、他に方法はありません。場所がたくさんあり、それらを地図に表示したい場合、最善の解決策は次のとおりです。
もちろん、これは、場所の相談よりも場所の作成/変更がはるかに少ないことを考慮したものです。
はい、それは場所を保存するときにもう少し作業をしなければならないことを意味します-しかしそれはまた意味します:
実際には、リクエストごとに1秒待つ必要はありません。各リクエストの間に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マップサービスの制限です。
私は現在、ジオコーディング機能を使用してアプリケーションに取り組んでおり、ユーザーごとに一意の各アドレスを保存しています。グーグルマップから返された情報に基づいて住所情報(都市、通り、州など)を生成し、緯度/経度の情報もデータベースに保存します。これにより、コードを再コーディングする必要がなくなり、適切にフォーマットされたアドレスが得られます。
これを実行するもう1つの理由は、特定のIPアドレスからジオコーディングできるアドレスの数に1日あたりの制限があるためです。その理由で、ある人のためにアプリケーションが失敗することは望ましくありません。
140のアドレスをジオコーディングしようとすると同じ問題が発生します。
私の回避策は、次のジオコーディング要求のループごとにusleep(100000)を追加することでした。リクエストのステータスがOVER_QUERY_LIMITの場合、usleepは50000増加し、リクエストが繰り返されます。
また、受信したすべてのデータ(lat / long)はXMLファイルに保存され、ページが読み込まれるたびにリクエストを実行しないようにします。
編集:
このソリューションは純粋なjsであると言うのを忘れました。必要なのは、promisehttps ://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);
}
});
}
};
これは、グーグルマップのものを処理するために私が書いたより大きなライブラリの一部にすぎないことに注意してください。したがって、コメントは混乱する可能性があります。
使用法は非常に簡単ですが、アプローチは少し異なります。一度に1つのアドレスをループして解決する代わりに、アドレスの配列をクラスに渡す必要があります。クラスはそれ自体で検索を処理し、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をテストしたところ、あなたと同じ問題が発生しました。OVER_QUERY_LIMITステータスが取得されるのは12リクエストごとに1回だけであることに気付いたので、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
}
}
それが役に立てば幸い