2012-08-03 64 views
32

我遇到了一個在這些論壇討論得很好的問題,但沒有任何建議似乎對我有用,所以我正在尋找一些完整的JavaScript,它在保存爲html文件時起作用。Google Maps API v3中的OVER_QUERY_LIMIT:如何暫停/延遲Javascript以減慢速度?

問題是當我嘗試使用JavaScript調用的V3 API在Google Map上對地理編碼> 11個位置進行地理編碼時,我總是碰到OVER_QUERY_LIMIT錯誤。我知道您可以調用地理編碼器的速率有限制(以及總量的每日限制),所以我需要在數組中的每個結果之間引入暫停。

非常感謝任何幫助。

這裏是我的代碼:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript"> 
var geocoder; 
var map; 
var wait = false; 


    function initialize() { 
geocoder = new google.maps.Geocoder(); 
var latlng = new google.maps.LatLng(51.32, 0.5); 



var myOptions = { 
    zoom: 8, 
    center: latlng, 
    mapTypeId: google.maps.MapTypeId.ROADMAP 
} 
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 
codeAddress('KT16 8LA' + ', UK'); 
codeAddress('LS8 2LQ' + ', UK'); 
codeAddress('NE13 8AF' + ', UK'); 
codeAddress('KT12 2BE' + ', UK'); 
codeAddress('W1W 8AN' + ', UK'); 
codeAddress('EC3N 2LS' + ', UK'); 
codeAddress('BS9 3BH' + ', UK'); 
codeAddress('KA10 6LZ' + ', UK'); 
codeAddress('EC1V 9BW' + ', UK'); 
codeAddress('WD18 8YN' + ', UK'); 
codeAddress('HA3 6DQ' + ', UK'); 
codeAddress('W1U 3PL' + ', UK'); 
codeAddress('W1T 7QL' + ', UK'); 
codeAddress('W1S 1TD' + ', UK'); 
codeAddress('SW1X 8NX' + ', UK'); 
codeAddress('LE2 8ET' + ', UK'); 
codeAddress('BA3 4BH' + ', UK'); 
codeAddress('AL3 8JP' + ', UK'); 
codeAddress('DE55 4QJ' + ', UK'); 
codeAddress('W6 0QT' + ', UK'); 
codeAddress('LA1 1PP' + ', UK'); 
codeAddress('SW16 4DH' + ', UK'); 
codeAddress('WC2N 6DF' + ', UK'); 
codeAddress('RM6 6LS' + ', UK'); 
codeAddress('S25 3QZ' + ', UK'); 
codeAddress('WC2H 7LR' + ', UK'); 
codeAddress('BH24 1DW' + ', UK'); 
codeAddress('EC2N 6AR' + ', UK'); 
codeAddress('W1U 2FA' + ', UK'); 
codeAddress('B60 3DX' + ', UK');  
} 

    function codeAddress(vPostCode) { 
if (geocoder) { 
    geocoder.geocode({ 'address': "'" + vPostCode + "'"}, function(results, status) { 
    if (status == google.maps.GeocoderStatus.OK) { 
     map.setCenter(results[0].geometry.location); 
     var marker = new google.maps.Marker({ 
      map: map, 
      position: results[0].geometry.location 
     }); 
    } else { 
     alert("Geocode was not successful for the following reason: " + status); 
    } 
    }); 
} 
} 

</script> 
<body style="margin:0px; padding:0px;" onload="initialize()"> 
<div id="map_canvas" style="width:100%; height:90%"></div> 
</body> 

編輯:這是我一直試圖做的就是它暫停/等待中的相關章節,但它不會做任何事情:

function codeAddress(vPostCode) { 
    if (geocoder) { 
    while (wait) { /* Just wait. */ }; 
     geocoder.geocode({ 'address': "'" + vPostCode + "'"}, function(results, status) { 
     if (status == google.maps.GeocoderStatus.OK) { 
      map.setCenter(results[0].geometry.location); 
      var marker = new google.maps.Marker({ 
       map: map, 
       position: results[0].geometry.location 
      }); 
     /* When geocoding "fails", see if it was because of over quota error: */ 
     } else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { 
     wait = true; 
     setTimeout("wait = true", 2000); 
     //alert("OQL: " + status); 
     } else { 
      alert("Geocode was not successful for the following reason: " + status); 
     } 
     }); 
    } 
    } 
+0

我認爲,如果你做你的要求,比如$ .getJSON ...... [在使用谷歌地圖OVER \ _query \ _LIMIT]沒有極限 – 2016-09-01 15:57:16

+0

可能的複製(http://stackoverflow.com/questions/3529746/over-query-limit-while-using-google-maps) – xomena 2016-11-06 13:22:37

回答

36

沒有像這兩條線會出現在邁克·威廉姆斯的教程:

wait = true; 
    setTimeout("wait = true", 2000); 

這裏有一個版本3端口:

http://acleach.me.uk/gmaps/v3/plotaddresses.htm

的代碼中的相關位是

// ====== Geocoding ====== 
    function getAddress(search, next) { 
    geo.geocode({address:search}, function (results,status) 
     { 
     // If that was successful 
     if (status == google.maps.GeocoderStatus.OK) { 
      // Lets assume that the first marker is the one we want 
      var p = results[0].geometry.location; 
      var lat=p.lat(); 
      var lng=p.lng(); 
      // Output the data 
      var msg = 'address="' + search + '" lat=' +lat+ ' lng=' +lng+ '(delay='+delay+'ms)<br>'; 
      document.getElementById("messages").innerHTML += msg; 
      // Create a marker 
      createMarker(search,lat,lng); 
     } 
     // ====== Decode the error status ====== 
     else { 
      // === if we were sending the requests to fast, try this one again and increase the delay 
      if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { 
      nextAddress--; 
      delay++; 
      } else { 
      var reason="Code "+status; 
      var msg = 'address="' + search + '" error=' +reason+ '(delay='+delay+'ms)<br>'; 
      document.getElementById("messages").innerHTML += msg; 
      } 
     } 
     next(); 
     } 
    ); 
    } 
+0

也適用於路由,當批量增加延遲後,只需遞歸到該批次的調用中即可。 – Brent 2014-05-28 16:42:17

+0

這是什麼.. @Andrew利奇你會好心告訴我什麼是這些延遲和下一個地址..你可以請解決這個[小提琴] – Prabs 2015-05-01 11:16:18

+0

'延遲'是延遲毫秒; nextAddress是地址計數器:如果地址失敗,則取消設置增量並增加延遲,以便可以再次嘗試。完整的實現是在我的網站上給出的鏈接:你的小提琴中沒有這樣的代碼。 – 2015-05-01 11:23:01

9

一般這個問題的答案是:

不要地理編碼已知位置每次加載頁面的時間。將它們離線編碼並使用得到的座標在頁面上顯示標記。

該限制存在的原因。

如果您無法對脫機地點進行地理編碼,請參閱Mike Williams的v2教程中的this page (Part 17 Geocoding multiple addresses),該教程描述了一種方法,將其移植到v3 API。

+0

感謝您的迴應。我無法將它們離線進行地理編碼,但您所引用的頁面沒有給出我可以應用的任何示例。我真正需要的是一個延遲/暫停步驟。 – user1573571 2012-08-03 10:11:28

+0

您是否看到以下內容:view-source:http://econym.org.uk/gmap/example_geomulti.htm,它是爲v2 API編寫的,但該概念應適用於v3 API。 – geocodezip 2012-08-03 10:26:03

+0

已經嘗試過這個概念,但沒有成功。它可能適用於V2和V3,但我無法將它成功應用於上述Javascript。 – user1573571 2012-08-03 11:21:11

3

使用「setInterval」&「clearInterval」解決了這個問題:

function drawMarkers(map, markers) { 
    var _this = this, 
     geocoder = new google.maps.Geocoder(), 
     geocode_filetrs; 

    _this.key = 0; 

    _this.interval = setInterval(function() { 
     _this.markerData = markers[_this.key]; 

     geocoder.geocode({ address: _this.markerData.address }, yourCallback(_this.markerData)); 

     _this.key++; 

     if (! markers[_this.key]) { 
      clearInterval(_this.interval); 
     } 

    }, 300); 
} 
0

您使用setTimeout走錯了路。 (其中之一)功能簽名是setTimeout(callback, delay)。因此,您可以輕鬆指定在什麼延遲之後應該運行哪些代碼。

var codeAddress = (function() { 
    var index = 0; 
    var delay = 100; 

    function GeocodeCallback(results, status) { 
     if (status == google.maps.GeocoderStatus.OK) { 
      map.setCenter(results[0].geometry.location); 
      new google.maps.Marker({ map: map, position: results[0].geometry.location, animation: google.maps.Animation.DROP }); 
      console.log(results); 
     } 
     else alert("Geocode was not successful for the following reason: " + status); 
    }; 

    return function(vPostCode) { 
     if (geocoder) setTimeout(geocoder.geocode.bind(geocoder, { 'address': "'" + vPostCode + "'"}, GeocodeCallback), index*delay); 
     index++; 
    }; 
})(); 

這樣一來,每一個codeAddress()調用將導致先前的呼叫後,以後geocoder.geocode()被稱爲100毫秒。

我還爲標記添加了動畫,因此您將有一個很好的動畫效果,標記被添加到一個接一個地圖中。我不確定當前的Google限制是多少,因此您可能需要增加delay變量的值。另外,如果您每次對相同的地址進行地理編碼,您應該將地理編碼的結果保存到您的數據庫中,下次只使用這些地址(這樣您將節省一些流量,並且您的應用程序會更快一些)

+0

如何將此代碼實現到我的代碼中? https://jsfiddle.net/395rdhd8/我嘗試了很多東西,但沒有任何運氣。 'STATUS OVER_QUERY_LIMIT'出現在我的控制檯中的'STATUS.OK'之前。但爲什麼? 謝謝。 – Appel 2017-03-03 15:12:44

+0

您對setTimeout的使用是錯誤的,setTimeout不會將JavaScript放入睡眠狀態X秒,它用於在X秒後運行指定函數 – Buksy 2017-03-05 22:09:32

+0

我該如何解決它? Javascript並不是我最強的技能。謝謝! – Appel 2017-03-06 07:49:43

3

這裏我已經加載了2200個標記。大約需要1分鐘才能添加2200個位置。 https://jsfiddle.net/suchg/qm1pqunz/11/

//function to get random element from an array 
    (function($) { 
     $.rand = function(arg) { 
      if ($.isArray(arg)) { 
       return arg[$.rand(arg.length)]; 
      } else if (typeof arg === "number") { 
       return Math.floor(Math.random() * arg); 
      } else { 
       return 4; // chosen by fair dice roll 
      } 
     }; 
    })(jQuery); 

//start code on document ready 
$(document).ready(function() { 
    var map; 
    var elevator; 
    var myOptions = { 
     zoom: 0, 
     center: new google.maps.LatLng(35.392738, -100.019531), 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
    map = new google.maps.Map($('#map_canvas')[0], myOptions); 

    //get place from inputfile.js 
    var placesObject = place; 
    errorArray = []; 

    //will fire 20 ajax request at a time and other will keep in queue 
    var queuCounter = 0, setLimit = 20; 

    //keep count of added markers and update at top 
    totalAddedMarkers = 0; 

    //make an array of geocode keys to avoid the overlimit error 
    var geoCodKeys = [ 
        'AIzaSyCF82XXUtT0vzMTcEPpTXvKQPr1keMNr_4', 
        'AIzaSyAYPw6oFHktAMhQqp34PptnkDEdmXwC3s0', 
        'AIzaSyAwd0OLvubYtKkEWwMe4Fe0DQpauX0pzlk', 
        'AIzaSyDF3F09RkYcibDuTFaINrWFBOG7ilCsVL0', 
        'AIzaSyC1dyD2kzPmZPmM4-oGYnIH_0x--0hVSY8'     
       ]; 

    //funciton to add marker 
    var addMarkers = function(address, queKey){ 
     var key = jQuery.rand(geoCodKeys); 
     var url = 'https://maps.googleapis.com/maps/api/geocode/json?key='+key+'&address='+address+'&sensor=false'; 

     var qyName = ''; 
     if(queKey) { 
      qyName = queKey; 
     } else { 
      qyName = 'MyQueue'+queuCounter; 
     } 

     $.ajaxq (qyName, { 
      url: url, 
      dataType: 'json' 
     }).done(function(data) { 
        var address = getParameterByName('address', this.url); 
        var index = errorArray.indexOf(address); 
        try{ 
         var p = data.results[0].geometry.location; 
         var latlng = new google.maps.LatLng(p.lat, p.lng); 
         new google.maps.Marker({ 
          position: latlng, 
          map: map 
         }); 
         totalAddedMarkers ++; 

      //update adde marker count 
         $("#totalAddedMarker").text(totalAddedMarkers); 
         if (index > -1) { 
          errorArray.splice(index, 1); 
         } 
        }catch(e){ 
         if(data.status = 'ZERO_RESULTS') 
          return false; 

      //on error call add marker function for same address 
      //and keep in Error ajax queue 
         addMarkers(address, 'Errror'); 
         if (index == -1) { 
          errorArray.push(address); 
         } 
        } 
     }); 

    //mentain ajax queue set 
     queuCounter++; 
     if(queuCounter == setLimit){ 
      queuCounter = 0; 
     } 
    } 

    //function get url parameter from url string 
    getParameterByName = function (name,href) 
    { 
     name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); 
     var regexS = "[\\?&]"+name+"=([^&#]*)"; 
     var regex = new RegExp(regexS); 
     var results = regex.exec(href); 
     if(results == null) 
     return ""; 
     else 
     return decodeURIComponent(results[1].replace(/\+/g, " ")); 
    } 

    //call add marker function for each address mention in inputfile.js 
    for (var x = 0; x < placesObject.length; x++) { 
     var address = placesObject[x]['City'] + ', ' + placesObject[x]['State']; 
     addMarkers(address); 
    } 
}); 
+1

ToS有一些限制,您應該注意: 「沒有超出交易限制和使用政策的限制如果您的Google Maps API實施產生大量交易,Google保留設置交易限制的權利,Google也有權隨時在文檔中設置其他使用政策。想要在這些交易限制或使用政策之外使用,您可以通過Maps API標準定價計劃購買更多的使用容量,或者您可以聯繫Google地圖銷售團隊獲取許可選項以滿足您的需求。「 – xomena 2016-11-07 11:08:46

+0

@sachingavas我得到的name.replace不是一個函數錯誤消息 – hyperfkcb 2017-12-16 12:22:24