javascript - 谷歌地理编码 - 关闭/循环问题

时间:2012-01-30 23:25:29

标签: javascript google-maps geocode

我在循环中反复调用google api函数。 每次我想删除地址数组的一个元素。

for(var i = 0; i < AddressObject.addressToArray.length; i++ ){              
  srPerformGeocode(AddressObject);    
  console.log(AddressObject.addressToArray);
  AddressObject.addressToArray.splice(0, 1);                
}
    // --------------------------------------------------------------
    //  Perform geocoding 
    // --------------------------------------------------------------
    function srPerformGeocode(AddressObject)
    {       
        address = AddressObject.addressToArray.join(",");   
        console.log(AddressObject.addressToArray);      
        if (geocoder){                      
            geocoder.geocode({'address': address.trim() }, function (results, status) 
            {                                           
                if (status == google.maps.GeocoderStatus.OK){                   
                    console.log("geocoded " + AddressObject.addressToArray);
                                        // Do something 
                }
                else{                   
                    alert("FAIL");
                }
            }); 
        }
    }

似乎正在发生的事情是循环运行了i次, 和函数srPerformGeocode每次运行i次 i循环的最后一个值。

['field1' ,'field2' ,'field3' ,'field4' ]
['field1' ,'field2' ,'field3' ]
['field1' ,'field2'  ]
['field1'  ]
geocoded field1
geocoded field1
geocoded field1
geocoded field1

2 个答案:

答案 0 :(得分:1)

这不是一个闭包问题,因为你从来没有关闭任何变量(address中的srPerformGeocode除外),但这对您的问题无关紧要)。 Read more about what closures are here.

JavaScript passes objects by reference 1 ,所以你在循环的每次迭代中传递相同的数组(因此,每次调用srPerformGeocode)。

在执行异步回调之前,这实际上很好 - 地理编码服务使用您在第一组控制台输出中看到的参数,但是当执行回调并且您记录“geocoded”时......“,你只会看到循环的最后一次迭代后它存在的AddressObject,因为循环很久以前就完成了(这是异步JavaScript的本质)。

解决问题的方法是通过srPerformGeocode数组的AddressObject 副本的每次调用。方便的是,数组有一个返回新数组的方法 - slice。 (splice仅修改数组;它不会创建新数组。)

for (var i = 0; i < AddressObject.addressToArray.length; i++) {              
 srPerformGeocode(AddressObject.slice(0, -i));
}

(请注意,这是一个浅拷贝;也就是说,数组中的任何对象仍然指向与原始数组相同的对象。这在此处无关紧要,因为您的数组充满了基元。)

其他一些说明:

    在IE≤8中不存在
  1. String.trim,因此您对address.trim()的调用将引发异常。
  2. Google地图并不真正进行批量地理编码;如果您拨打太多地理编码电话,您可能会发现自己的速率受限甚至完全关闭。

  3. 1 学生不同意这一说法;请参阅linked答案。

答案 1 :(得分:0)

当地理编码API调用您的回调时,AddressObject.addressToArray已更改。你最好坚持你传递的字符串(而不是对象)。

我怀疑这会给你你想要的结果:

console.log("geocoded " + address.trim());