AngularJS - Load Google maps w/ promise

by gavinfoley

HTML

<div data-ng-app="myApp">
    <div data-ng-controller="MyCtrl"> 
        <span data-ng-bind="notify"></span> 
    </div>
</div>

CSS

</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> 
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script> 
<style>

JavaScript

//Include angular-ui dependency in resources on the side and as 'ui'
angular.module('myApp', [])

.controller("MyCtrl", function ($scope, utils) {
    $scope.notify = "Waiting for Google Map...";
    
    utils.loadGoogleMaps().then(function () {
        $scope.notify = "Google Maps loaded!";
    }, function(reasonFailed) { // optional failed callback
        console.log('Failed: ' + reasonFailed);
    }, function(notify){ // optional notify/progress callback
        console.log(notify);
    });
})

.factory('utils', ['$timeout', '$window', '$q', function ($timeout, $window, $q) {

    var utils = {};  
    
    // Load Google Maps
    utils.loadGoogleMaps = function () {
        return utils.loadScript("http://maps.google.com/maps/api/js?v=3&sensor=false", function () {
            return typeof $window.google !== 'undefined' // is Google in the window
        }, "Google Maps");
    };
    
    // Load script (local or external)
    utils.loadScript = function (scriptSrc, scriptLoadedCheck, name) {
        var script = document.createElement("script");        
        script.src = scriptSrc;
        document.getElementsByTagName("head")[0].appendChild(script);

        return utils.poll(scriptLoadedCheck, null, null, name);
    };
    
    // Polls to check when a variable is defined.
    utils.poll = function (whenReady, interval, timeout, name) {
        var deferred = $q.defer(),
            i = parseInt(interval, 10) || 50, // default to 50 milliseconds
            t = parseInt(timeout, 10) || 10000; // default: poll for 10 seconds
       
        (function poll() {
            var me = this;
            if (whenReady.apply(me)) { // poll check func satisfied
                deferred.resolve();
            } else if ((t -= i) > 0) { // poll again
                deferred.notify("Polling " + (name || ""))
                $timeout(poll, i);
            } else { // timeout reached
                deferred.reject("Poll timeout reached " + (name || ""));
        ...