简体   繁体   中英

Problem with Google Maps and JavaScript for() loop

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?

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 )

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 :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM