简体   繁体   中英

Issue with asynchronous function and scope of javascript variable

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

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

});

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;

};

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM