Wrap outside-angular service.

http://stackoverflow.com/questions/16957039/angularjs-async-callback-return-undefined-under-scope-apply

by Zmetser

HTML

<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<div ng-controller="MyCtrl">
    <p ng-show="$loading">Wait a second...</p>
    <p>Hello, {{name}}!</p>
    <button ng-hide="$loggedIn" ng-click="login()">Log me in!</button>
</div>

JavaScript

var myApp = angular.module('myApp',[]);

myApp.factory('myService', ['$q', '$timeout', function( $q, $timeout ) {
    var auth = {},
        deferred;
    
    auth.login = function () {
        deferred = $q.defer();
        
        doLogin();
        
        return deferred.promise;
    }
    
    function doLogin() {
        // setTimeout to mock behaviour of an ourside-angular service. Like FirebaseAuthClient
        window.setTimeout(function () {
            $timeout(function () {
                deferred.resolve({name: 'Oliver'})
            }, 0);
        }, 1000);
    }
    
    return auth;
}]);

myApp.controller('MyCtrl', ['$scope', 'myService', function ($scope, myService) {
    $scope.name = 'Guest';
    $scope.login = function () {
        $scope.$loading = true;
        myService.login()
            .then(loginSuccess, loginFailure);
    }
    
    function loginSuccess( user ) {
        $scope.$loading = false;
        $scope.$loggedIn = true;
        $scope.name = user.name;
    }
    function loginFailure( error ) {
        
    }
}]);