【问题标题】:Bypassing geocodes query limit with settimeout使用 settimeout 绕过地理编码查询限制
【发布时间】:2017-01-12 14:45:28
【问题描述】:

因此,我正在测试一个脚本,该脚本将从数组中获取城市,然后使用地理编码找到它们的坐标,然后获取城市的 zip。好吧,这在一个城市可以正常工作,但是对于一个数组,geoCode 有一个查询限制,所以我试图用 setTimeout 绕过它,但是由于我对 js 还不是很了解,所以它不起作用。

<head>
    <div id= "test"></div>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

   <script type="text/javascript">

    function getLoc(){  
        var geocoder = new google.maps.Geocoder();
        var address = ["Helsinki", "Paris", "London"];
        for (var i = 0; i < address.length; i++)    {
            setTimeout(function(i){ 
            geocoder.geocode( { 'address': address[i]}, function (results, status) {    
            if (status == google.maps.GeocoderStatus.OK) {
                var lat = results[0].geometry.location.lat();
                var long = results[0].geometry.location.lng();
                alert(long);
                getZip(lat, long);

                }
            });
            }, i* 1000);
        }
        }
        getLoc();
    function getZip(lat, long){
        var latlng = new google.maps.LatLng(lat, long);
        geocoder.geocode({
        'latLng': latlng
        }, function(results, status) {
            address = results[0].address_components;
            zipcode = address[address.length - 1].long_name;
            document.getElementById("test").innerHTML = zipcode;
        }); 
    }
</script>
</head>
<body>

</body>

【问题讨论】:

  • 我相信您对最后一个城市“伦敦”有所了解?
  • 超时有效,但它没有通过第一个地理编码请求
  • 我不知道您的用例或数据集的大小,但您可能需要考虑编写一个服务器端 cron 作业,在后台获取数据(使用适当的限制)并存储它在数据库中。 API 限制对于实时批处理来说太低了,并且在客户端上故意添加延迟会使访问者感到沮丧。
  • @Álvaro González 是的,我确实读过它,但我不会在任何公共场合使用它,我这样做只是为了让自己更轻松。我可能还是会为了好玩而尝试使用它。感谢您的建议

标签: javascript arrays settimeout geocoding


【解决方案1】:
 for (var i = 0; i < address.length; i++) { 
 (function(i){
  setTimeout(function(i){ 
    geocoder.geocode( { 'address': address[i]}, function (results, status) { if (status == google.maps.GeocoderStatus.OK) { var lat = results[0].geometry.location.lat(); var long = results[0].geometry.location.lng(); alert(long); getZip(lat, long); } });
   }, i* 1000);
   })(i);
}

for 循环将在超时触发之前完成。所以我在所有超时中将永远是 adress.length-1。您需要使用 IIFE 将 i 存储在每个超时范围内(可以查看 SO 上的“for 循环中的超时”)

正如@iwrestledabearonce 指出的那样,使用超时并不是一种优雅的方式。您可以一次使用多个打开请求,也可以一个接一个。对于第一个你不需要超时,对于第二个,递归函数是一个更优雅的解决方案。

【讨论】:

    【解决方案2】:

    您需要将setTimeout 包装在闭包函数中,例如:

    for (var i = 0; i < address.length; i++) {
        (function(i){
            setTimeout(function(i){ 
                geocoder.geocode( { 'address': address[i]}, function (results, status) {    
                    if (status == google.maps.GeocoderStatus.OK) {
                        var lat = results[0].geometry.location.lat();
                        var long = results[0].geometry.location.lng();
                        alert(long);
                        getZip(lat, long);
    
                    }
                });
            }, i* 1000);
        })(i);
    }
    

    如果不关闭,setTimeout 中的 i 将始终具有上一个 for 迭代的值

    【讨论】:

    • 为什么有人减去这个答案...?
    • 我解释了为什么这个答案和上面的答案在我自己的答案中是错误的。问题是,为什么有人赞成一个不正确的答案?
    • @Iwrestledabearonce。那么你能解释一下为什么这是错误的吗?实现您编写的内容是另一种方式,它的工作方式相同,但您使用的是回调函数。
    • 不,我不能,因为它没有错。我只是没有注意。我没有注意到i* 1000。我的错。我删除了投票。
    • @我喜欢你的名字就和一只熊搏斗了,我还能再看看你的例子吗?
    猜你喜欢
    • 1970-01-01
    • 2016-09-21
    • 2012-06-24
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 1970-01-01
    相关资源
    最近更新 更多