Google Geocoder v3를 사용하여 20 개의 주소를 지오 코딩하려고하면 ~ 1 초 간격으로 시간을 설정하지 않으면 OVER_QUERY_LIMIT가 표시되지만 마커가 모두 배치되기까지 20 초가 걸립니다.
좌표를 미리 저장하는 것 외에 다른 방법이 있습니까?
답변
아니요, 다른 방법은 없습니다. 위치가 많고지도에 표시하려는 경우 가장 좋은 방법은 다음과 같습니다.
- 위치가 생성 될 때 지오 코더를 사용하여 위도 + 경도를 가져옵니다.
- 주소와 함께 데이터베이스에 저장
- 지도를 표시하고 싶을 때 저장된 위도 + 경도를 사용합니다.
물론 이것은 위치에 대한 상담보다 위치 생성 / 수정이 훨씬 적다는 것을 고려할 때입니다.
예, 위치를 저장할 때 더 많은 작업을 수행해야하지만 다음을 의미합니다.
- 지리적 좌표로 검색 할 수 있습니다.
- 예 : ” 지금 현재 위치에 가까운 지점 목록을 원합니다. “
- 지도 표시가 훨씬 빨라집니다.
- 20 개 이상의 위치가있는 경우에도
- 아, 그리고 (마지막으로 중요한) : 이것은 작동합니다 😉
- N 초 내에 X 지오 코더 호출 한도에 도달 할 가능성이 적습니다.
- 그리고 하루에 Y 지오 코더 호출 한도에 도달 할 가능성이 적습니다.
답변
실제로 각 요청에 대해 1 초를 기다릴 필요가 없습니다. 각 요청 사이에 200 밀리 초를 기다리면 OVER_QUERY_LIMIT 응답을 피할 수 있고 사용자 경험이 통과 할 수 있다는 것을 알았습니다. 이 솔루션을 사용하면 4 초 내에 20 개의 항목을로드 할 수 있습니다.
$(items).each(function(i, item){
setTimeout(function(){
geoLocate("my address", function(myLatlng){
...
});
}, 200 * i);
}
답변
안타깝게도 이것은 Google지도 서비스의 제한 사항입니다.
현재 지오 코딩 기능을 사용하는 응용 프로그램에서 작업 중이며 각 고유 주소를 사용자별로 저장하고 있습니다. Google지도에서 반환 한 정보를 기반으로 주소 정보 (시, 거리, 주 등)를 생성 한 다음 위도 / 경도 정보도 데이터베이스에 저장합니다. 이렇게하면 코드를 다시 코딩 할 필요가 없으며 멋진 형식의 주소를 얻을 수 있습니다.
이를 수행하려는 또 다른 이유는 특정 IP 주소에서 지오 코딩 할 수있는 주소 수에 일일 제한이 있기 때문입니다. 그런 이유로 신청이 실패하는 것을 원하지 않습니다.
답변
140 개의 주소를 지오 코딩하려는 것과 동일한 문제에 직면 해 있습니다.
내 해결 방법은 다음 지오 코딩 요청의 각 루프에 대해 usleep (100000) 을 추가하는 것 입니다. 요청 상태가 OVER_QUERY_LIMIT이면 usleep이 50000 증가하고 요청이 반복됩니다.
그리고 수신 된 모든 데이터 (위도 / 경도)는 페이지가로드 될 때마다 요청을 실행하지 않도록 XML 파일에 저장됩니다.
답변
편집하다:
이 솔루션은 순수 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지도를 처리하기 위해 작성한 더 큰 라이브러리의 일부일 뿐이므로 댓글이 혼란 스러울 수 있습니다.
사용법은 매우 간단하지만 접근 방식은 약간 다릅니다. 한 번에 하나의 주소를 반복하고 확인하는 대신 클래스에 주소 배열을 전달해야하며 검색을 자체적으로 처리하여 약속을 반환합니다. , 확인되면 확인 된 (및 확인되지 않은) 주소를 모두 포함하는 배열을 반환합니다.
예:
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
}
}
도움이되기를 바랍니다.