Search code examples
javascriptgoogle-mapsasynchronousrequirejs

Asynchronous Google Maps loading bug in IE


I've had a look for this bug all over the place and not found anything that works. Here's the code:

MapsLoader.prototype._setup = function () {
    var promise = new RSVP.Promise(function (resolve) {

        // Callback for Google Maps that resolves the promise
        window.gmapsLoaded = function () {
            console.log('[Maps Loader] Loaded');
            resolve();
        };

        console.log('[Maps Loader] Loading...');

            // Create a URL with the API key pointing to the gmapsLoaded callback
        var mapsURL = 'https://maps.googleapis.com/maps/api/js?key=' + config.googleMaps.APIKey + '&sensor=false&callback=gmapsLoaded',

            // Create script object
            script = $('<script />').attr('src', mapsURL);

        $('head').append(script);
    });

    // Remove the gmapsLoaded function from global scope
    promise.then(function () {
        window.gmapsLoaded = undefined;
    });

    // Return the promise
    return promise;
};

It's part of a MapsLoader module that simply adds in the Google Maps script to the head (only when required), waits for the Google Maps load callback, and then resolves the promise (at which point the file that uses it can start doing stuff).

Works well in Safari, Chrome, Firefox, and IE10. However in IE 8 and 9 I get an error:

  • Object doesn't support property or method 'Load' (IE9)
  • Object doesn't support property or method (IE8)

Which is coming from line 55 of the main.js Google Maps file:

k.google.maps.Load(...)

This occurs after the "[Maps Loader] Loaded" log message, so the callback is running and the page continues to load normally except that the Google Maps area is blank.

If I turn caching on (i.e. not using IE Developer Tools) the page will sometimes work the second time, suggesting it's perhaps some sort of loading race condition.

I was able to fix it by loading the Google Maps code in the head in conditional comments, so it would only load on all pages in IE (and then detecting if google already exists in the MapsLoaded module). This did work, but it's not pleasant and I'd rather find the route cause.


Other information: I use RequireJS for module loading.

Things I've tried:

  • Using the async=2 parameter on the Google Maps URL (as suggested here)
  • Appending to the body instead of head (as on the Google API examples)
  • Placing everything in a $.ready call

Thanks


Solution

  • Using $.getScript(mapsURL) (i.e. loading it via an AJAX request) instead of manually appending a script to the head seemed to work.

    Not sure why loading it in this way should make a difference, but it did.