能够访问服务返回的对象,但访问其属性会给出未定义的

Able to access object returned by service, but accessing its properties gives undefined

我是一个 angular 初学者,我正在尝试建立一个从我的 php 后端获取数据并更新控制器的工厂。这是我的基本代码:

工厂

app.factory('sessionStatus', ['$http', function($http){
    return {
        status:function(){
            var status = {};
            $http.get('/game_on/api/api.php?session-status')
            .then(function(response){
                angular.copy(response.data, status);
            });
            return status;
        }
    };
}]);

控制器

app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus){

    $scope.sessionStatus = sessionStatus.status();

    console.log($scope.sessionStatus);

}]);

这会在控制台中显示以下内容:

Object{}
  session:"false"

但是,当我调整控制器以记录会话的值时 属性,如下所示:

console.log($scope.sessionStatus.session);

我只是在控制台中得到 undefined。

我做错了什么?

编辑

对于任何其他患有我独特的迟钝品牌的人,这是我得出的结论:

问题的主要原因是我一直在尝试访问 $http 服务返回的异步生成的信息,该信息在它的 promise 被解决之前(即在 .then() 完成执行之前),这是导致记录未定义,因为数据实际上尚未定义,因为在控制器中调用 console.log() 时生成数据的请求仍在进行中。

使用 $timeout 服务我能够延迟 console.log() 的调用,这导致数据被正确记录到控制台。

$timeout(function(){
    console.log($scope.sessionStatus.session);
}, 2000); // logs "false" to the console like originally expected

我之前的想法是,我应该在控制器中尽可能短地调用我的工厂方法,然后在调用之外根据其结果采取行动。这显然是个坏主意,因为 .then() 存在,因此您可以在请求完成的准确时刻对异步请求的结果采取行动。

事后看来,这一切似乎都很明显,但希望这个解释能在未来帮助其他人...

感谢我收到的所有答复,他们帮了我大忙!

因为 javascript 是异步的,它不会等到 http 响应和 return 状态。这就是为什么它 return 为空。尝试这样的事情

   app.factory('sessionStatus', ['$http', function($http){
            return {
                status:function(){
                 $http.get('/game_on/api/api.php?session-status')
                }
            };
        }]);

        app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus){

            $scope.sessionStatus = sessionStatus.status().then(function(response) { 
               console.log(response);
        });


    }]);

尝试return你factory的承诺:

app.factory('sessionStatus', ['$http', function($http) {
  var factory = {
    status: status
  };

  return factory;

  function status() {
    return $http.get('/game_on/api/api.php?session-status');
  }
}]);

然后在控制器:

app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus) {
  function getSuccess(response) {
    $scope.sessionStstus = response.data;
  }

  function getError(response) {
    console.log('error');
  }

  sessionStatus.status()
    .then(getSuccess)
    .catch(getError);

  console.log($scope.sessionStatus);
}]);

您可以对此处的代码进行一些更改。首先,我建议解决承诺并在控制器中而不是在服务中分配值。接下来,您不需要在结果对象上使用 Angular.Copy ,您可以简单地进行变量赋值。尝试像这样简单的事情,然后构建:

app.factory('sessionStatus', ['$http', function($http){

    return {status: $http.get('/game_on/api/api.php?session-status')}

}]);

app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus){

    sessionStatus.status.then(function(result){
        $scope.sessionStatus = result.data; //or some property on result
    });

}]);