我在循环中反复调用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
答案 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));
}
(请注意,这是一个浅拷贝;也就是说,数组中的任何对象仍然指向与原始数组相同的对象。这在此处无关紧要,因为您的数组充满了基元。)
其他一些说明:
String.trim
,因此您对address.trim()
的调用将引发异常。1 学生不同意这一说法;请参阅linked答案。
答案 1 :(得分:0)
当地理编码API调用您的回调时,AddressObject.addressToArray
已更改。你最好坚持你传递的字符串(而不是对象)。
我怀疑这会给你你想要的结果:
console.log("geocoded " + address.trim());