Reputation: 39449
I have a website where users can search for professional wrestling events in the United Kingdom by entering there location. The site uses the Google Maps API and a bespoke API to query the database and return the events via AJAX.
The JavaScript function I'm using to iterate over results from my API looks like this:
function setMarkers(map, events) {
var geocoder = new google.maps.Geocoder();
for (var i=0; i < events.length; i++) {
var wrestling_event = events[i];
console.log(wrestling_event);
var image_a = '/images/marker.png';
var image_b = '/images/marker-over.png';
geocoder.geocode({ address: wrestling_event.venue.post_code }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
icon: image_a
});
var infowindow = new google.maps.InfoWindow({
content: '<p><strong>' + wrestling_event.date + ': ' + wrestling_event.name + '</strong><br />' +
wrestling_event.venue.name + ',<br />' +
wrestling_event.venue.street_address + ',<br />' +
wrestling_event.venue.city + ',<br />' +
wrestling_event.venue.post_code + '</p>'
});
google.maps.event.addListener(marker, 'mouseover', function() {
marker.setIcon(image_b);
});
google.maps.event.addListener(marker, 'mouseout', function() {
marker.setIcon(image_a);
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
}
});
}
};
This is adapted from the Google Maps API sample, found here: http://code.google.com/apis/maps/documentation/javascript/examples/icon-complex.html
The issue I'm having is, if I have multiple results returned from the bespoke API, my JavaScript function is printing the same event over and over, despite logging the result of the wrestling_event
object.
The wrestling_event
variable seems to get overwritten (or not after the first iteration in the for()
loop) inside the geocoding block. Is there a reason for this?
Upvotes: 2
Views: 1700
Reputation: 57721
See my answer How to pass parameter to an anonymous function defined in the setTimeout call?
Short answer: it's because the call to the geocoder
is asynchronous (like setTimeout
)
Upvotes: 3
Reputation: 414056
Yes, there's a reason - all the callback functions constructed in the loop share the same variable.
Code blocks in loops do not create a new scope in the way they do in languages like Java or C#. Only functions create new scopes.
What you could do is write a separate function that returns the handler. You'd pass that "wrestling_event" into the function, and it can return the callback code you've got. You'd then pass that return value in as the callback parameter to the "geocode()" routine.
This is such a common pitfall in JavaScript that it should be described on the back cover of every book on the language :-)
Upvotes: 1