Domanda

Here's my code in the service.

this.loginUser = function(checkUser) {
    Parse.User.logIn(checkUser.username, checkUser.password, {
        success: function(user) {
            $rootScope.$apply(function (){
                $rootScope.currentUser = user;
            });
        }
    });
};

Here's my code in the controller:

$scope.logIn = function(){
    authenticationService.loginUser($scope.checkUser);
        console.log($scope.currentUser)
};

So, what I want to do is, execute some code AFTER the completion of AJAX call, whose success function sets the value of $scope.currentUser, which, I can use for some conditional logic (like redirecting etc) The success function is correctly setting the value, but the console.log should be executed AFTER the execution of authenticationService.loginUser() function.

È stato utile?

Soluzione

You need to return a promise using $q and act on that.

For instance in your service:

this.loginUser = function(checkUser) {
    var deferred = $q.defer();
    Parse.User.logIn(checkUser.username, checkUser.password, {
        success: function(user) {
            $rootScope.$apply(function (){
                $rootScope.currentUser = user;
            });
            deferred.resolve();
        }
    });
    return deferred.promise;
};

Then in your controller act on the success:

$scope.logIn = function(){
    authenticationService.loginUser($scope.checkUser).then(function() {
        console.log($rootScope.currentUser));
    });
};

Altri suggerimenti

Try using $rootScope.$broadcast in your service then listen for it in your controller:

Service

Parse.User.logIn(checkUser.username, checkUser.password, {
    success: function(user) {
        $rootScope.$apply(function (){
            $rootScope.currentUser = user;
            $rootScope.$broadcast('user.online');
        });
    }
});

Controller

$scope.$on('user.online',function(){
    [ DO STUFF HERE ]
});

This isn't the best way to do this though @comradburk's use of $q is probably a better way.

If your application wait for external result, you should use $q for return a promise. If you are using angular-route or ui-router components, you can use resolve param for this. Take a look ngRoute documentation. In there has a example based in resolve param.

https://docs.angularjs.org/api/ngRoute/service/$route

i think you have two options here

  1. as answered by comradburk, use promises:

in Services:

this.loginUser = function(checkUser) {
var deferred = $q.defer();
Parse.User.logIn(checkUser.username, checkUser.password, {
    success: function(user) {
        deferred.resolve(user);
    }
});
return deferred.promise;

};

in controller:

$scope.logIn = function(){
authenticationService.loginUser($scope.checkUser).then(function(user) {
    $scope.currentUser = user;
});
};
  1. using resolve, resolve your service at route level (...or state level in case you are using ui-router) before controller initialization and insert it as a dependency - helpful in scenarios like user authentication where you dont want user to be able to navigate further if authentication fails. from docs https://docs.angularjs.org/api/ngRoute/service/$route

YOMS (Yet One More Solution):

    this.loginUser = function(checkUser, onSuccess) {
        Parse.User.logIn(checkUser.username, checkUser.password, {
            success: function(user) {
                $rootScope.$apply(function() {
                    $rootScope.currentUser = user;
                    if (typeof onSuccess == 'function') onSuccess(user); // optionally pass data back
                });
            }
        });
    };

    $scope.logIn = function(user, function(returnedUser) {
    // console.log(returnedUser); // Optional, The returned user
        console.log($scope.currentUser)
    }) {
        authenticationService.loginUser($scope.checkUser);
    };
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top