angular $http 承诺被返回两次

angular $http promise being returned twice

我正在尝试将 if 语句中的表达式计算为 return truefalse。该函数的评估取决于 $http promises,其中的文档非常丰富 - 所以我有信心我可以弄清楚这一点。

但是,我注意到我的控制台有些奇怪,那就是 .success 回调似乎被 运行 两次,因为控制台输出成功回调的输出两次(即 the call was a success 被记录了两次)!

通过查看代码,我的理解是 save() 导致 securityCheck.checkLogin() 记录 undefined,if 语句评估为 false(从而记录 function returned false),然后承诺 return 和 the call was a success 被记录一次。为什么它被记录两次?

脚本

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

谢谢!

你确实意识到,你正在调用 checkLogin() 方法两次:

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

这会导致 $http.get() 执行两次,您的 success 实施也是如此。

您在指令中调用了一次 console.log,然后在工厂函数中又调用了一次。

// 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!');

虽然命令不同,但它们return值相同

那么删除 console.log(securityCheck.checkLogin()); 并且请求将只发出一次。但是,这只是您的代码的小问题。真正的一个是您将 AJAX 请求视为同步请求,但事实并非如此。 checkLogin 方法不 return true/false 它 return 承诺对象,并且是异步的。

您应该在 then 回调中检查身份验证结果:

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

你还需要制作工厂方法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;
}]);

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