Exactly. It's the way that the browser processes the Javascript. Your for loop calls the function addMarker(), which then makes a call to the geocoder and immediately returns control back to the for loop. Later on when the geocoder responses are received, the anonymous callback function is called, which then sets the bounds and adds the markers, etc. By that point, map.fitBounds has already been called.
Below is your original code with some logging added in (and a new DIV in the HTML for the logs). If you run it, you should see output similar to the following under the map:
addMarker called for Newtown, NSW
addMarker called for Newcastle, NSW
Calling fitBounds()
After fitBounds()
Successful geocode returned for Newtown, NSW
Extending bounds for Newtown, NSW
Finished extending bounds for Newtown, NSW
Successful geocode returned for Newcastle, NSW
Extending bounds for Newcastle, NSW
Finished extending bounds for Newcastle, NSW
HTML:
Javascript:
// Accepts an array of gigs
function initializeMap(gigs) {
var markers = gigs;
// Create geocoder
var geocoder = new google.maps.Geocoder();
// Create the map
var map = new google.maps.Map(document.getElementById("gigpress-map"), {
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Create infowindow
var infowindow = new google.maps.InfoWindow({
content: "holding..."
});
// Create boundary
var bounds = new google.maps.LatLngBounds();
// Add markers to map
for (index in markers) addMarker(markers[index]);
function addMarker(data) {
// Geocoder
log("addMarker called for " + data.city);
geocoder.geocode({
'address': data.city
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
log("Successful geocode returned for " + data.city);
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
title: data.venue
});
// Add to boundary
log("Extending bounds for " + data.city);
bounds.extend(results[0].geometry.location);
log("Finished extending bounds for " + data.city);
// Bind click event to each marker
google.maps.event.addListener(marker, "click", function() {
infowindow.open(map, this);
});
} else {
log("Unsuccessful geocode returned for " + data.city);
}
});
}
// Zoom and center the map to fit the markers
log("Calling fitBounds()");
map.fitBounds(bounds);
log("After fitBounds()");
}
function log(text) {
document.getElementById("log").innerHTML += text + "<br/>";