Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

This is my factory code. The callback is async so i put it under $rootScope.safeApply(). Then I call console.log(authService.authUser) in my controller but it still return undefined when user logged in. But it is find if user not login and will show 'not login' in console. Any idea?

myapp.factory('authService', ['$rootScope', function($rootScope) {
    var auth = {};
    $rootScope.safeApply = function(fn) {
      var phase = this.$root.$$phase;
      if (phase == '$apply' || phase == '$digest') {
        if(fn && (typeof(fn) === 'function')) {
            fn();
        }
      } else {
        this.$apply(fn);
      }
    };    
    auth.firebaseAuthClient = new FirebaseAuthClient(FIREBASEREF, function(error, user) {
        $rootScope.safeApply(function() {
            if (user) {
                auth.authUser = user;
                //auth.isLoggedIn = true;
            } else if (error) {
                auth.authError = error;
            } else {
                auth.not = 'not login';
                //auth.isLoggedIn = false;
            }
        });
    });

    auth.login = function() {
        this.firebaseAuthClient.login('facebook');
    };

    auth.logout = function() {
        this.firebaseAuthClient.logout();   
    };

    return auth;
}]);

UPDATED

auth.callback = function(error, user) {
    if (user) {
        deferred.resolve(user);
    } else if (error) {
        deferred.reject(error);
    } else {
        //deferred.reject('not login');  // there is no callback value here
    }
    return deferred.promise;
}

in controller

callback().then(function(response) {
  $scope.isLoggedIn = true;
}, function(response) {
  $scope.isLoggedIn = false //How can i set false here?
});

UPDATE 2

Now every thing work fine, I'm able to monitoring user login state. But still having a problem. Check the code below

authService.callback().then(function(success){
  $rootScope.isLoggedIn = true; //If promise return success set isLoggedIn true
}, function(fail){
   **//If user not login set isLoggedIn false;
   //I have problem here because i'm not able to deferred.reject below**
  $rootScope.isLoggedIn = false;
})

auth.callback = function(error, user) {
    $timeout(function() {
        if (user) {
            deferred.resolve(user);
        } else if (error) {
            deferred.reject(error);
        } else {
            //If this line is added,
            //.then() will not return anything not even undefined with no error,
            //No mater user logged-in or not login.
            //If I comment it out, everything will work fine but how can I 
            //set isLoggedIn = false?
            deferred.reject(); 
        }

    }, 0);
    return deferred.promise;
}
share|improve this question
 
Use promises instead of that hacky safeApply stuff. docs.angularjs.org/api/ng.$q –  Olivér Kovács Jun 6 at 8:36
 
@OlivérKovács hi, i updated my question using $q ..can you check it again? –  vzhen Jun 6 at 10:22
add comment

1 Answer

Wrap the outside service's deferred resolve in a $timeout block to let angular know when its resolved. This way when your controller runs then callback, it'll be in a $digest cycle.

See this fiddle as a working proof of concept: http://jsfiddle.net/Zmetser/rkJKt/

// in controller
authService.login().then(success, error);

// service
myapp.factory('authService', ['$q', '$timeout', function( $q, $timeout ) {
    var auth = {},
      deferred;

    firebaseAuthClient = new FirebaseAuthClient(FIREBASEREF, afterAuth);

    function afterAuth( error, user ) {
        // Let angular know the deferred has been resolved.
        $timeout(function () {
          if (user) {
              deferred.resolve(user);
          } else if (error) {
              deferred.reject(error);
          } else {
              deferred.reject();  // there is no callback value here
          }
        }, 0);
    }

    auth.login = function() {
        deferred = $q.defer();
        firebaseAuthClient.login('facebook');

        return deferred.promise;
    };

    auth.logout = function() {
        deferred = $q.defer();
        firebaseAuthClient.logout(); 

        return deferred.promise;  
    };

    return auth;
}]);
share|improve this answer
 
Thanks, but what if i want afterAuth() standalone? because I want to use it to check user login state without trigger .login('facebook') –  vzhen Jun 6 at 13:05
 
basically, i want to check if user logged-in in every route –  vzhen Jun 6 at 13:24
 
AfterAuth is a callback. How do you want is standalone? Once the user logged in save the state to the service, or get it from the server, when you want. auth.loggedIn() –  Olivér Kovács Jun 6 at 13:47
 
Ok, let me try again... come back later. –  vzhen Jun 6 at 13:58
 
Ok, after some tries, return promise in .login() and .logout() is not what I want. What I meant standalone is actually pull the callback out from FirebaseAuthClient. This is because I can use authService.afterAuth().then() to monitoring user login state without trigger .login(). Now everything work find but there is still a problem. Please check my update2 –  vzhen Jun 6 at 18:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.