22
\$\begingroup\$

Here is a simple reusable AngularJS factory I came up with to initialize Google Maps Asynchronously, which somehow does not seem to be supported by major libraries (see below):

Following Google's guidelines I am using global callback function (which seems to be unavoidable harm), that resolves a dummy promise, which is the only API returned.

Then maps can be loaded anywhere by simply calling

Initializer.mapsInitialized.
 .then(function(){
 map = new google.maps.Map(element, options);
 });

Below is the code. Any critics, potential flaws, drawbacks, violation of best practices is welcome!

// Google async initializer needs global function, so we use $window
angular.module('GoogleMapsInitializer')
 .factory('Initializer', function($window, $q){
 // maps loader deferred object
 var mapsDefer = $q.defer();
 // Google's url for async maps initialization accepting callback function
 var asyncUrl = 'https://maps.googleapis.com/maps/api/js?callback=';
 // async loader
 var asyncLoad = function(asyncUrl, callbackName) {
 var script = document.createElement('script');
 //script.type = 'text/javascript';
 script.src = asyncUrl + callbackName;
 document.body.appendChild(script);
 };
 // callback function - resolving promise after maps successfully loaded
 $window.googleMapsInitialized = function () {
 mapsDefer.resolve();
 };
 // loading google maps
 asyncLoad(asyncUrl, 'googleMapsInitialized');
 return {
 // usage: Initializer.mapsInitialized.then(callback)
 mapsInitialized : mapsDefer.promise
 };
 })

Most major libraries built for Google Maps seem to use the standard script tag

<script src='//maps.googleapis.com/maps/api/js'></script>

which is, however, blocking, may result in delays, and makes the page unsuitable for offline testing.

On another note, library such as script.js async loader, does not seem to work with this particular script.

asked Aug 11, 2014 at 7:54
\$\endgroup\$
0

1 Answer 1

13
\$\begingroup\$

I like it,

you could clean up the commented out code and possibly replace

 $window.googleMapsInitialized = function () {
 mapsDefer.resolve();
 };

with

 $window.googleMapsInitialized = mapsDefer.resolve;

Personally, I would re-arrange the code a tiny bit, keep the URL completely on top, keep asyncLoad and the call closer together. Keep the declaration of mapsDefer and the resolving function closer.

// Google async initializer needs global function, so we use $window
angular.module('GoogleMapsInitializer')
.factory('Initializer', function($window, $q){
 //Google's url for async maps initialization accepting callback function
 var asyncUrl = 'https://maps.googleapis.com/maps/api/js?callback=',
 mapsDefer = $q.defer();
 //Callback function - resolving promise after maps successfully loaded
 $window.googleMapsInitialized = mapsDefer.resolve; // removed ()
 //Async loader
 var asyncLoad = function(asyncUrl, callbackName) {
 var script = document.createElement('script');
 //script.type = 'text/javascript';
 script.src = asyncUrl + callbackName;
 document.body.appendChild(script);
 };
 //Start loading google maps
 asyncLoad(asyncUrl, 'googleMapsInitialized');
 //Usage: Initializer.mapsInitialized.then(callback)
 return {
 mapsInitialized : mapsDefer.promise
 };
})
answered Nov 14, 2014 at 16:15
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.