无法访问服务中的数据

时间:2012-12-20 11:06:47

标签: angularjs

我有一个要求,我想从服务器检索JSON对象。以下是两个不起作用的版本 -

版本1

app.service("authorization", ['$http', function($http){
  var authMap = [];
  $http.get('/authmap').success(function(data){this.authMap = data});
}]);

第2版

app.service("authorization", ['$http', function($http){
  var authMap = [];
  $http.get('/authmap').success(function(data){authMap = data});

  var getAuthMap = function(){return authMap};
}]);

在第一版中,我将服务注入到我的控制器中并以authorization.authMap的形式访问它,它返回一个空的[]。

在第二版中,我将其作为authorization.getAuthMap()访问。在这里它给我一个错误,没有在对象上定义这样的方法?

这两种方法有什么问题?

3 个答案:

答案 0 :(得分:2)

只需将变量作为该服务范围的一部分

app.service("authorization", ['$http', function($http){
    var authorizationScope = this;
    authorizationScope.authMap = [];
    $http.get('/authmap').success(function(data){authorizationScope .authMap = data});
}]);

第2版

app.service("authorization", ['$http', function($http){
    var authorizationScope = this;
    authorizationScope.authMap = [];
    $http.get('/authmap').success(function(data){authorizationScope.authMap = data});

    authorizationScope.getAuthMap = function(){return authorizationScope.authMap};
}]);

当你注入它时,你的控制器可以访问那个变量或函数

function myController($scope, authorization){
    authorization.authMap //this is how you would access the variable here
    authorization.getAuthMap(); //this is how you would access the function
}

答案 1 :(得分:1)

  1. 你应该公开你的功能。
  2. 您需要了解$ http是异步调用。最简单的修复方法是将$ http承诺返回给您的控制器并解析那里的数据。
  3. 所以:

    app.service("authorization", ['$http', function($http){
      return {
         getAuthMap : function(){
            return $http.get('/authmap');
         }
      };
    }]);
    

    在您的控制器中:

    authorization.getAuthMap().then(function(data) {
        $scope.data = data;
    });
    

    如果数据很复杂且应在您的服务中处理,您可以在服务中使用service $ q并将其承诺返回给您的控制器。这使得服务稍微复杂一些:

    app.service("authorization", ['$http', '$q', function($http, $q) {
    
      var authMap;
    
      return {
         getAuthMap : function(){
            var deferred = $q.defer();
            var promise = deferred.promise;
    
            promise.then(function() {
               if (!authMap) {
                  $http.get('/authmap').success(function(data) {
                     var changedData = data;
                     // do sth with data
                     authMap = changedData;
    
                     deferred.resolve(changedData);
                  });
               } else {
                  deferred.resolve(authMap)
               }
            });
            return deferred.promise;
         }
      };
    }]);
    

答案 2 :(得分:1)

您已经在另一篇文章中询问了版本1,并在那里得到了答案:Unable to set a class var in $http callback

总结:使用设置为全局上下文的函数上下文(即this)调用success()和error()方法(即window)。因此this.authMap = data将数据存储在window.authMap中,而不是存储在您的服务中。您需要创建一个闭包(通过定义局部变量并将其设置为this),然后在success()函数中使用该变量:

app.service("authorization", ['$http', function($http){
  this.authMap = [];
  var self = this;
  $http.get('/authmap')
     .success(function(data){
        self.authMap = data
     })
     .error(function(data, status){
        alert('Unable to authorize')
        console.log(status)
     })
}]);

版本2有两个问题:

  1. 与版本1相同的问题
  2. 您正在使用service(),因此服务函数的主体需要是JavaScript构造函数(因为Angular将通过在构造函数上调用new来实例化服务)。因此,需要在this
  3. 上定义公共属性(包括函数/方法)
    app.service("authorization", ['$http', function($http){
       this.authMap = [];
       this.getAuthMap = function(){ return this.authMap };
       var self = this;
       $http.get('/authmap')
          .success(function(data){
             self.getAuthMap = data
          })
          .error(function(data, status){
             alert('Unable to authorize')
             console.log(status)
          })
    }]);
    

    如果你想保持authMap私有,请使用factory()代替:

    app.factory("authorization", ['$http', function($http){
       var authMap = [];         // private data
       $http.get('/authmap')
          .success(function(data){
             authMap = data
          })
          .error(function(data, status){
             alert('Unable to authorize')
             console.log(status)
          })
       return {
          getAuthMap: function() { return authMap };
       }
    }]);