1

I have the following code that calls an REST webservice. The web service returns a boolean.

    checkCurrentPassword: function (passwordInfo) {
        var valid = false;
        $http.post('/api/preference/password/check', passwordInfo)
            .success(function (data) {
                valid = data;
            });
        return valid;
    }

The trouble is that by the time the checkCurrentPassword returns valid is still false because the ajax call has not completed due to its asynchronous nature.

I am not sure how to make sure the valid variable is properly assigned the value returned from the server.

Can anyone please help?

edit 1:

Using a callback, It seems I am only deporting the problem to the controller layer... See below:

from angular service:

checkCurrentPassword: function (passwordInfo, callback) {
              return  $http.post('/api/preference/password/check', passwordInfo)
                    .success(function (data) {
                        callback(data);
                    });
            }

from angular controller:

 $scope.updatePassword = function () {
            if ($scope.updatePasswordForm.$valid) {

                var valid = false;

                passwordService.checkCurrentPassword({plainPassword: $scope.passwordInfo.currentPassword}, function(data, status){
                    valid = data;
                });

                console.log(valid);//always false

                passwordService.updatePassword($scope.passwordInfo, function (data, status) {
                    console.log('Updated password successfully');
                    $state.go('dashboard');
                });
            }
        };

edit 2: here is how I rewrote the controller:

$scope.updatePassword = function () {
            if ($scope.updatePasswordForm.$valid) {
                passwordService.checkCurrentPassword({plainPassword: $scope.passwordInfo.currentPassword}).success(function (data) {
                    if (data) {
                        passwordService.updatePassword($scope.passwordInfo, function (data, status) {
                            console.log('Updated password successfully');
                            $state.go('dashboard');
                        });
                    }
                });
            }
        };
balteo
  • 23,602
  • 63
  • 219
  • 412

3 Answers3

1

You should return the promise (HttpPromise) returned by $http.get, see: https://docs.angularjs.org/api/ng/service/$q and https://docs.angularjs.org/api/ng/service/$http

This example may help you:

angular.module('app',[]);

angular.module('app').service('Foo',function($q){

  this.checkPassword = function(value){
    //replace this example code with a $http call
    console.log('checkPassword:',value);
    var deferred = $q.defer();
    setTimeout(function(){
      if(value && value.length >= 4){
        deferred.resolve(value);        
      } else {
        deferred.reject('oops invalid password!!!');
      }   
    },100);
    return deferred.promise;
  };

  this.updatePassword = function(value){
    //replace this example code with a $http call
    console.log('updatePassword:',value);
    var deferred = $q.defer();
    setTimeout(function(){
      if(Math.random() > 0.5){
        deferred.resolve('password updated');        
      } else {
        deferred.reject('error while updating password');
      }   
    },100);
    return deferred.promise;
  };

});

angular.module('app').run(function(Foo){

  Foo.checkPassword('tolkjlkj')
    .then(Foo.updatePassword)
    .then(function(result){
      console.log('Yes',result);
    }).catch(function(error){
      console.log('Oops',error);
    });

});
OXMO456
  • 3,558
  • 2
  • 25
  • 35
  • The issue is that I need a plain boolean from the caller/client side. – balteo Dec 16 '14 at 14:40
  • @balteo - There is no way to accomplish that. You can't force an asynchronous operation to block and wait. You have to consume a promise, or use a callback. – Josh Dec 16 '14 at 14:42
1

You should use angulars's built in $q service

You're function would look something like this. (make sure to inject $q into your code at the top)

checkCurrentPassword: function (passwordInfo) {

    var deferred = $q.defer();
    var valid = false;

    $http.post('/api/preference/password/check', passwordInfo)
        .success(function(data){
            valid = data;
            deferred.resolve();
        })
        .error(function(error){
            deferred.reject();
        });

    return deferred.promise;

};

Community
  • 1
  • 1
MHX
  • 1,581
  • 2
  • 21
  • 31
0

I think you could solve it with the callbacks...

checkCurrentPassword: function (passwordInfo) {

  $http.post('/api/preference/password/check', passwordInfo)
             .success(function (data) {
                 return data;
             }).error(function (data) {
                 return false;
             });

}
  • It seems you are returning data from the inner function. I need to return it from the outer function... – balteo Dec 16 '14 at 14:42