1

In angular JS i am having unexpected behovier. I have a log in controller where when i execute Log in function

$scope.Login = function () {

    AuthService.login($scope.credentials).then(function(response){
        $location.path('/categories');
    },
     function(error){
        $scope.error_exist = true;
     switch(error.ExceptionMessage){
        case "201" :
             $scope.error = "The emailAddress/password pair don't match an existing member"; break;
        case "210" :
             $scope.error = "Value cannot be null missing Email Address and/or password."; break;
        case "202" :
             $scope.error = "The email address you are using isn't confirmed. Please see your inbox for further instructions."; break;
        default : 
             $scope.error = "Error with the server";
     }
    });
};

What happens is that the log in function in AuthService get executed then when it hit AccountService.GetUserAccounts which is another function in a service it calls back $location.path('/categories'); which were in the Log in controller after that it continues to execute normally what i want is to call $location.path('/categories'); after Log in function in AuthService get finished. her is the AuthService

return $http.post(AuthentoctionControllerUrl, credentials).success(function(response){
               Session.create(response.Name,response.id, response.UserMail);
               AccountService.GetUserAccounts(response.id).then(function(){
                  var acc = AccountService.getAccounts();
                  AccountService.SetUserAccount(acc[0], response.UserMail).then(function(){
                      accIsSet.accSet = true;
                  },
                  function(error){
                      console.log(error);
                  });
               },
               function(error){
                   console.log(result);
               });

            deferred.resolve(response);
           }).error(function(error){
               deferred.reject(error);
           });

            return deferred.promise;
        };

Also AccountService

AccountFactory.GetUserAccounts = function(userID){
            var deferred = $q.defer();
            return $http({method : "post", url:ConfigService.baseUrl+UserURl, data: userID})
                         .success(function(response){
                            for(var i = 0; i<response.length; i++)
                            userAccounts.push(response[i].AccName);
                            $cookieStore.put("userAccounts",userAccounts);
                            deferred.resolve(response);
                         }).error(function(error){
                            deferred.reject(error);
                            console.log(error);
                         });
                return deferred.promise;
        };

        AccountFactory.SetUserAccount = function(accName, userMail){
            var deferred = $q.defer();
                        return $http({method : "post", url:ConfigService.baseUrl+AccountUrl+"?accName="+accName+"&userMail="+userMail})
                         .success(function(response){
                            $cookieStore.put('AuthorizationHeader', response.Token);
                            AccSession.create(response.IsAdmin);
                            deferred.resolve(response);
                         }).error(function(error){
                            deferred.reject(error);
                            console.log(error);
                         });
                return deferred.promise;
        };
AccountFactory.getAccounts = function(){
    if(userAccounts)
        return userAccounts;
    else
        return null;
};

Her is an edit of the code and i still get the same behavior.

 authService.login = function(credentials) {
           return $http.post(AuthentoctionControllerUrl, credentials).success(function(response){
               Session.create(response.Name,response.id, response.UserMail);
              return AccountService.GetUserAccounts(response.id).then(function(){
                  return AccountService.getAccounts();
              }).then(function(acc) {
                 return AccountService.SetUserAccount(acc[0], response.UserMail);
              }).then(function() {
                      accIsSet.accSet = true;
              });
           });
        };
 AccountFactory.GetUserAccounts = function(userID){
           return $http({method : "post", url:ConfigService.baseUrl+UserURl, data: userID})
                         .success(function(response){
                            console.log("ssss");
                            for(var i = 0; i<response.length; i++)
                            userAccounts.push(response[i].AccName);
                            $cookieStore.put("userAccounts",userAccounts);
                             return response;
                         });
        };

        AccountFactory.SetUserAccount = function(accName, userMail){
                        return $http({method : "post", url:ConfigService.baseUrl+AccountUrl+"?accName="+accName+"&userMail="+userMail})
                         .success(function(response){
                            $cookieStore.put('AuthorizationHeader', response.Token);
                            AccSession.create(response.IsAdmin);
                            return response;
                         });
        };

        AccountFactory.getAccounts = function(){
            if(userAccounts)
                return userAccounts;
            else
                return null;
        };

        return AccountFactory;
    }]);

2 Answers 2

2

$http services when invoked, returns a promise. A promise has methods .then(), .catch(), .finally() which returns a promise as well. Additionally, the $http service's .success() and .error() methods returns a promise. Thus, creating a promise via $q.defer() and resolving it like that is redundant. If you want to get the response value on success you can simply return it as shown below.

Change your AuthService.login() to return something like this:

return $http.post(AuthentoctionControllerUrl, credentials)
    .success(function(response) {
        Session.create(response.Name,response.id, response.UserMail);

        return AccountService.GetUserAccounts(response.id)
            .then(function(acc) {
                return AccountService.SetUserAccount(acc[0], response.UserMail);
            }).then(function() {
                accIsSet.accSet = true;
            });
    });

and your AccountFactory to this:

AccountFactory.GetUserAccounts = function(userID){
    return $http({method : "post", url:ConfigService.baseUrl+UserURl, data: userID})
         .success(function(response){
            for(var i = 0; i<response.length; i++)
                userAccounts.push(response[i].AccName);
            $cookieStore.put("userAccounts",userAccounts);
            return response;
         });
};

AccountFactory.SetUserAccount = function(accName, userMail){
    return $http({method : "post", url:ConfigService.baseUrl+AccountUrl+"?accName="+accName+"&userMail="+userMail})
        .success(function(response){
            $cookieStore.put('AuthorizationHeader', response.Token);
            AccSession.create(response.IsAdmin);
            return response;
        });
};

Note: Error Handling should be within the controller logic, unless for special cases wherein you need to change some states within the factory/service itself then that would be an exception. If you would catch the errors, make sure to return the response so that error handlers within the controllers/factories/services that depend on it can still access the response.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for pointing out error handling. but i am still having the same behavior where $location.path('/categories'); get executed before var acc = AccountService.getAccounts(); in the Auth service
I have made minor changes in AuthService.login() to show how chaining promises work. Check if it works.
AccountService.getAccounts(); dose not make HTTP request i will edit my question to show it sorry and i am still have the same beauvoir
I have updated AuthService.login() since AccountFactory.GetUserAccounts() returns the response on success it should be available when invoking .then(). Please check update.
I followed your instructions i could post my edit your Code ? i get same behavior
|
1

I manged to solve the problem by the help of @ryeballar

authService.login = function(credentials) {
            var defferd = $q.defer();
            $http.post(AuthentoctionControllerUrl, credentials).success(function(response){
               Session.create(response.Name,response.id, response.UserMail);
              return AccountService.GetUserAccounts(response.id).then(function(acc){
                  if(acc.data.length !=0)
                    return AccountService.SetUserAccount(acc.data[0].AccName, response.UserMail);
                  else
                      return 0;
              }).then(function(data) {
                  if(data)
                    accIsSet.accSet = true;

                  defferd.resolve(response);
              });
           }).error(function(error){
                defferd.reject(error);
            });
                return defferd.promise;
        };

Modified the Auth service to resolve the promise at the end of success method so the method in the controller will fire as expected

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.