Angularjs异步回调在$ scope下返回undefined。$ apply();

时间:2013-06-06 08:19:48

标签: angularjs angularjs-service

这是我的工厂代码。回调是异步的所以我把它放在$ rootScope.safeApply()下。 然后我在我的控制器中调用console.log(authService.authUser),但是当用户登录时它仍然返回undefined。但是如果用户没有登录并且在控制台中显示“not login”,则会发现它。有什么想法吗?

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;
}]);

已更新

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;
}
控制器中的

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

更新2

现在一切正常,我能够监控用户登录状态。但仍有问题。检查下面的代码

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;
}

1 个答案:

答案 0 :(得分:0)

将外部服务的延迟解析包装在$ timeout块中,让角度知道何时解析。这样,当你的控制器运行然后回调时,它将处于$ digest周期。

将此小提琴看作是一个有效的概念证明: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;
}]);