2012-08-03 68 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