nikk wong
nikk wong

Reputation: 8690

angular $http promise being returned twice

I am trying to evaluate an expression in an if statement to return true or false. The function's evaluation depends on $http promises, of which the documentation out there is plentiful—so I'm confident I can get this figured out.

However, I noticed something odd in my console, and that is that it seems the .success callback is being ran twice, as the console is outputting the output from the success callback twice (i.e. the call was a success is being logged twice)!

From looking at the code, my understanding would be that the save() causes securityCheck.checkLogin() to log undefined, the if statement to evaluate to false (thereby logging function returned false), and then the promise to return with the call was a success to be logged once. Why is it being logged twice?

script

angular.module('login', ['security'])
.directive('loginDirective', ['$parse', 'securityCheck', function($parse, securityCheck) {
    return {
    scope: true,
    link: function(scope, element, attrs, form) {
      scope.save = function() {
        console.log(securityCheck.checkLogin());
           //evaluates to undefined, promise not returned yet
        if (securityCheck.checkLogin()) {
          console.log("function returned true");
        } else {
          console.log("function returned false");
        }
      }
    }
    };
}]);

angular.module('security', [])
.factory('securityCheck', ['$q', '$http', function ($q, $http) {
    var security = {
    checkLogin: function() {
        $http.get('https://api.mongolab.com/api/1/databases/lagrossetete/collections/avengers?apiKey=j0PIJH2HbfakfRo1ELKkX0ShST6_F78A')
            .success(function(data, status, headers, config) {
                console.log('the call was a success!');
            })
            .error(function(data, status, headers, config) {
                console.log('the call had an error.');
            });
    }
    };
    return security;
}]);

html

<html ng-app="login">
  <body>
    <login-directive ng-click="save()">click me</login-directive>
  </body>
</html>

plnkr: http://plnkr.co/edit/tM7eHniDRvCLhzAw7Kzo?p=preview

Thanks!

Upvotes: 1

Views: 1031

Answers (3)

dfsq
dfsq

Reputation: 193311

Well remove console.log(securityCheck.checkLogin()); and request will be issued only once. However this is only minor problem with your code. Real one is that you treat AJAX request as if it was synchronous, however it's not. checkLogin method doesn't return true/false it returns promise object, and asynchronously.

You should check for auth result inside of then callback:

link: function(scope, element, attrs, form) {
  scope.save = function() {
      securityCheck.checkLogin().then(function(check) {
        if (check) {
          console.log("function returned true");
        } else {
          console.log("function returned false");
        }
      });
  }
}

You also need to make factory method return promise:

angular.module('security', [])
.factory('securityCheck', ['$q', '$http', function ($q, $http) {
    var security = {
    checkLogin: function() {
        return $http.get('https://api.mongolab.com/api/1/databases/lagrossetete/collections/avengers?apiKey=j0PIJH2HbfakfRo1ELKkX0ShST6_F78A')
            .success(function(data, status, headers, config) {
                console.log('the call was a success!');
                return data;
            })
            .error(function(data, status, headers, config) {
                console.log('the call had an error.');
            });
    }
    };
    return security;
}]);

Demo: http://plnkr.co/edit/Kj8PkLMv3PsLfe9fsaRo?p=preview

Upvotes: 1

Nick Moreton
Nick Moreton

Reputation: 228

You call the console.log once in your directive and then once again in your factory function.

// Here in the directive
scope.save = function() {    
    console.log(securityCheck.checkLogin());

// And then here in the service
.success(function(data, status, headers, config) {
            console.log('the call was a success!');

Although different commands, they both return the same value

Upvotes: 1

npe
npe

Reputation: 15719

You do realize, you are calling checkLogin() method twice:

 console.log(securityCheck.checkLogin());
    //evaluates to undefined, promise not returned yet
 if (securityCheck.checkLogin()) {

This causes $http.get() to be executed twice, and so is your success implementation.

Upvotes: 2

Related Questions