I am calling a google api function repeatedly in a loop.
Each time i want to remove one element of the address array.
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");
}
});
}
}
What appears to be happening is that the loop is running i times,
and function srPerformGeocode is running i times each time using
the last value of the i loop.
['field1' ,'field2' ,'field3' ,'field4' ]
['field1' ,'field2' ,'field3' ]
['field1' ,'field2' ]
['field1' ]
geocoded field1
geocoded field1
geocoded field1
geocoded field1
This isn’t a closure issue, because you never actually close over any variables (other than
addressinsrPerformGeocode, but that’s inconsequential to your problem). Read more about what closures are here.JavaScript passes objects by reference1, so you’re passing the same array around on each iteration of the loop (and thus, each invocation of
srPerformGeocode).This is actually fine until the asynchronous callback is executed – the geocoding service is called with the parameters you see in the first set of console outputs, but when the callback is executed and you log “geocoded …”, you’ll only see
AddressObjectas it existed after the last iteration of the loop, because the loop finished a long time ago (this is very nature of async JavaScript).The way to fix your problem is to pass each invocation of
srPerformGeocodea copy of theAddressObjectarray. Conveniently, arrays have a method that return a new array –slice. (spliceonly modifies an array; it does not create a new one.)(Note that this is a shallow copy; that is, any objects in the array still point to the same objects as the original array. This doesn’t matter here since your array is full of primitives.)
Some other notes:
String.trimdoesn’t exist in IE ≤ 8, so your call toaddress.trim()will throw an exception.1 Pedants will disagree with this statement; see the linked answer.