控制器内部未定义的变量($scope 问题)

Undefined Variable Inside Controller ($scope issue)

全部,我下面有以下AngularJS。为什么 $scope.gotData 在调用 getData.success() 之外不可见?请注意 $scope.gotData 对视图可见:我可以通过将 {{gotData}} 放在我的 index.html.

中来显示 scope.gotData 的值

为什么我不能在控制器的其他地方将 $scope.gotData 作为变量访问?这是一个关于 $scope.

细节的问题

getData.js

myApp.factory('getData',function($http){
return $http.jsonp('https://foo.com/bar.json')
       .success(function(data){
            return data;
        })
        .error(function(err){
            return err;
        });
});

MainController.js

myApp.controller('MainController', ['$scope','getData', function($scope, getData){
    getData.success(function(data){
        $scope.gotData = data;
    });

    $scope.gotData /* NOT DEFINED HERE */
   }]);

index.html

<html>
  <head>
    <script src="js/vendor/angular.js"></src>
  </head>
  <body ng-app="MyApp">
    <div ng-controller="MainController">
      {{gotData}} /* I CAN SEE THE DATA HERE */
     </div>
  </body>
</html>

对 getData.success 的调用是异步的。因此,在执行该成功函数之前,您对 $scope.gotData 的控制台的调用已完成。所以你应该预先定义这个 $scope.gotData 的默认值。当您接到成功电话时,您才应该使用它。像这样:

myApp.controller('MainController', ['$scope','getData', function($scope,getData){

    $scope.gotData = null;

    getData.success(function(data){
        $scope.gotData = data;
    });

    if($scope.gotData != null) 
        // Do something useful with this data
}]);

为什么在 getData.success() 函数之外看不到 $scope.gotData 的原因是因为 .success()async 并且当您尝试在 .success() 之外访问它时该值不可用。这实质上意味着承诺尚未解决。

此外,一旦 angular 的摘要周期确定 $scope.gotData 已填充,它就会快速更新视图。这就是 为什么您可以在视图中看到 $scope.gotData 的原因

$scope.gotData

上加上 watch 之后事情会更清楚
 myApp.controller('MainController', ['$watch','$scope','getData', function($watch,$scope, getData){
     getData.success(function(data){
        $scope.gotData = data;
     });

    $scope.$watch($scope.gotData,function(n,o){
       console.log("new val-> "+n);
       console.log("old val->"+o);
     })   
 }]);

虽然不是最好的编程实践,但解决这个问题的方法是使用 $rootScope。

myApp.controller('MainController', ['$scope','getData', function($scope, getData){
    getData.success(function(data){
        $rootScope.gotData = data;
    });

    console.log($rootScope.gotData) // this will be accessible across
                                    // different controllers aswell
   }]);