用$ http注入服务会搞砸控制器

时间:2015-12-10 15:02:50

标签: angularjs

我创建了一个使用$ http发布登录数据并获取身份验证令牌的服务,但每当我将其注入控制器时,它就会中断(看起来像html看不到它)。当我删除服务注入,或者使用$ resource注入一个服务注入时,一切正常。 这是服务的代码:

    MyApp.service('LoginSrv', ['$http', function User($http) {
         var userData = {
         isAuthenticated: false,
         username: '',
         bearerToken: '',
         expirationDate: null,
      };

    function setHttpAuthHeader() {
          $http.defaults.headers.common.Authorization = 'Bearer ' + userData.bearerToken;
        }

     this.getUserData = function(){
         return userData;
};

this.authenticate = function(username, password, successCallback, errorCallback) {
      var config = {
            method: 'POST',
            url: '/accounts/login',
            headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                },
        data: 'grant_type=password&username=' + username + '&password=' + password,
      };

  $http(config)
    .success(function(data) {
          userData.isAuthenticated = true;
          userData.username = data.userName;
          userData.bearerToken = data.access_token;
          userData.expirationDate = new Date(data['.expires']);
          setHttpAuthHeader();
          if (typeof successCallback === 'function') {
                successCallback();
              }
        })
    .error(function(data) {
          if (typeof errorCallback === 'function') {
                if (data.error_description) {
                      errorCallback(data.error_description);
                    } else {
                  errorCallback('Unable to contact server; please, try again later.');
                }
          }
    });
};
  }]);

这是控制器代码:

    MyApp.controller('mainCtrl', function ($scope, LoginSrv)
{
    $scope.loginUsername = 'Jan';
    $scope.loginPassword = 'Maria';
    $scope.userLogin = new LoginSrv();
    $scope.loginError = false;
    function onSuccesfulLogin () {};
    function onFailedLogin(error) {};
    $scope.login = function () {
        userLogin.authenticate($scope.loginUsername, $scope.loginPassword, onSuccesfulLogin, onFailedLogin);
    }; 

});

2 个答案:

答案 0 :(得分:1)

Services are singleton so you need not give a "new"

我做了一个简短的例子,说明了你需要的相同流程并且运作良好,我希望能提供帮助:

  

服务

angular.module("yourapp").factory('LoginSrv', function User($http) {
        var _authenticate = function(username, password) { 
          console.log('logged') 
        };
        return {
            authenticate: _authenticate
        };
});
  

控制器

angular.module("yourapp").controller('mainCtrl', function ($scope, $http, LoginSrv)
        {
            $scope.loginUsername = 'Jan';
            $scope.loginPassword = 'Maria';
            $scope.userLogin = LoginSrv;
            $scope.loginError = false;
            $scope.login = function () {
                userLogin.authenticate($scope.loginUsername, $scope.loginPassword);
            }; 
});

答案 1 :(得分:1)

另一个答案很好地解释了您的LoginSrv相关例外,并解释了如何实施服务/工厂。然而,它没有注意到的是两者之间的差异。

<强>工厂 注入工厂时,由于调用工厂功能,将为您提供返回值

<强>服务 注入服务时,您将获得服务功能的实例。这类似于new serviceFunction();。重要的是要注意angular会在第一次注入服务时执行此操作,所有其他时间注入它将会收到相同的实例。

因此,工厂用于创建对象(因此名称),服务意味着服务。所以共享逻辑。

所以在我看来(这就是全部)你的现有服务正试图做到这两点。您似乎拥有要创建的用户对象,但也有用于验证用户的方法。最好将该用户对象放在工厂中,该工厂返回create方法以创建新用户。然后将身份验证逻辑放入服务中。然后,您的身份验证不会直接与您的用户实现相关联。

可能的实施(伪代码)

.factory('userFactory', function () {
    return {
        create: function (details) {
            return Object.create({}, {
                username: {
                    value: details.username
                },
                password: {
                    value: details.password
                },
                isAuthenticated: {
                    value: false
                }
            });
        }
    }  
});

.service('auth', function ($http) {
    this.authenticate = function (username, password) {
        //Build config
        return $http();
    }
});

.controller('test', function ($scope, userFactory, auth) {
    var user =  userFactory.create({
        username: 'hiya',
        password: 'epic secrets'
    });

    auth.authenticate(user.username, user.password)
        .then(function (d) {
            user.isAuthenticated = d.isAuthenticated;
        })
        .catch(SomeGenericErrorHandler);
});

任何问题只需询问