Christophvh Christophvh - 5 months ago 152
Javascript Question

Google maps v3 API only loading after refresh / Authentication goes very slow

Using Google maps v3 API. When i visit the page with the map i sometimes get following error :

"custom.js:46 Uncaught ReferenceError: google is not defined"
.

API's enabled on the key:


  • Google Maps Directions API

  • Google Maps Distance Matrix API

  • Google Maps Elevation API

  • Google Maps Geocoding API

  • Google Maps JavaScript API



When i reload the page, everything is working fine. This doesn't work 100% of the time. Multiple reloads are needed on some occasions.

I did notice that when the map isn't loading correctly this script is running in my head tags:

<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps/api/js/AuthenticationService.Authenticate?1shttp%3A%2F%2Fmayan-co.com%2Fen%2Foutlets&amp;MYKEY&amp;callback=_xdc_._h7cv8d&amp;token=60166"></script>


After 10-20 seconds this script goes away and when i refresh the page after this script goes away, my map is working correctly.

Things i tried without results:


  • Putting the script to load the API in the footer.

  • Not using async or defer.

  • Adding specific url's to my api key.

  • Not using a api key



Loading the api script in the Head of my page:

<script src="https://maps.googleapis.com/maps/api/js?key=MYKEY" async defer></script>


My script to render the map and place markers on the map (loaded in the footer)

jQuery(document).ready(function($) {
$('#animation').addClass('animate');

$('.heart img').popover({
placement: 'top',
html: true,
container: '#animation',
content: function () {
return $(this).attr('alt');
}
});

$('body').on('click', function(e) {
$('.heart img').each(function() {
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.heart img').has(e.target).length === 0) {
$(this).popover('hide');
} else {
$(this).popover('toggle');
}
});
});

function render_map($el) {

var $markers = $(document).find('#locations .data-source li');

var args = {
zoom: 16,
center: new google.maps.LatLng(0, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP]
}
};

var map = new google.maps.Map($el[0], args);

map.markers = [];

index = 0;
$markers.each(function() {
add_marker($(this), map, index);
index++;
});

center_map(map);
}

function add_marker($marker, map, index) {
var latlng = new google.maps.LatLng($marker.attr('data-lat'), $marker.attr('data-lng'));
var image = '../../img/maps-leaf.png';
var marker = new google.maps.Marker({
position: latlng,
map: map,
icon: image
});
map.markers.push(marker);
if ($marker.html()) {
$('#locations .data-display').append('<li class="linkage" id="p'+index+'">'+$marker.html()+'</li>');

$(document).on('click', '#p' + index, function() {
infowindow.open(map, marker);
setTimeout(function() { infowindow.close(); }, 5000);
});

var infowindow = new google.maps.InfoWindow({
content: $marker.html(),
});

google.maps.event.addListener(marker, 'click', function() {
infowindow.open( map, marker );
});
}
}

function center_map(map) {
var bounds = new google.maps.LatLngBounds();
$.each( map.markers, function( i, marker ){
var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
bounds.extend( latlng );
});

if( map.markers.length == 1 ) {
map.setCenter( bounds.getCenter() );
map.setZoom( 16 );
} else {
map.fitBounds( bounds );
}
}

$(document).ready(function(){
$('#map').each(function(){
render_map( $(this) );
});
});
});

Answer

What you describe looks like you try to instantiate the map before the Google Maps API JavaScript is loaded (you're using async attribute there). That's why it sometimes throws google is not defined error.

In other words, document.ready is called before https://maps.googleapis.com/maps/api/js?key=MYKEY is loaded.

Google Maps API allows you to use callback parameter in the URL with a name of a function that's called after the API is fully loaded. See https://developers.google.com/maps/documentation/javascript/tutorial.

So in your case you'll use URL like:

https://maps.googleapis.com/maps/api/js?key=MYKEY&callback=initMap

And then initialize the map:

initMap() {
    var map = new google.maps.Map($el[0], args);
}