I had to solve the problem of integrating AngularJS and RequireJS with Google Maps. This is not usually a huge challenge, there is even an async module for RequireJS, and an Angular-UI map plugin to make integration pretty seamless. The wrinkle that made this integration trickier is AlmondJS—and Almond doesn’t support asynchronous module loading.
When you include the Google Maps script, you can specify a callback in the querystring that will fire when the Google Maps API is loaded. You could then bootstrap your Angular app in that callback, e.g.:
This will work, but it will block your app until you hear back from Google Maps. I didn’t want to do that; there was only one spot where a user might use the map. Therefore, I wanted to lazily load it.
When you are configuring the $routeProvider
, you can specify an object for the route
parameter’s resolve
property. Each property on the resolve
object is a function that can return a promise. The controller will not get instantiated until the promise is resolved. And when the promise is resolved, the value returned from the promise resolution gets passed into the controller as a parameter.
So the plan of action was to resolve a promise when Google Maps was ready.
Here’s more-or-less how I implemented the gmap
function.
With this approach, we don’t risk blocking the entire app; just this one route might block. Of course, this example just shows how to handle the “happy path”; it doesn’t handle if the Maps API fails to load for some reason. I also wound up extending it to return the current positions coordinates, instead of just true
when the maps API is ready. That is left as an exercise for the reader …