Undefined Variable Inside Controller ($scope issue

2019-08-09 07:44发布

问题:

All, I have the following AngularJS below. Why is $scope.gotData not visible outside of the call to getData.success()? Note that $scope.gotData is visible to the view: I can display the value of scope.gotData by placing {{gotData}} within my index.html.

Why can I not access $scope.gotData as a variable elsewhere in my controller? This is a question concerning the details of $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>

回答1:

The reason why you cannot see $scope.gotData outside the getData.success() function is because .success() is async and the value is not available when you try to access it outside .success(). This essentially means that the promise has not been resolved yet.

Moreover, once angular's digest cycle identifies that $scope.gotData is populated, it quickly updates the view. Thats the reason why you can see $scope.gotData in the view

Things would be more clear once you put a watch on $scope.gotData

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


回答2:

the call to getData.success is asynchronous. So before executing that success function, your call to console of $scope.gotData is done. So you are supposed to define a default value of this $scope.gotData beforehand. And when you get a success call, only then you should use it. Something like this :

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


回答3:

Although not the best programming practice, but a solution to this is to use $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
   }]);