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

时间:2015-07-12 18:48:57

标签: javascript angularjs http callback scope

全部,我在下面有以下AngularJS。为什么$scope.gotData在调用getData.success()之外不可见?请注意,视图可以看到$scope.gotData:我可以scope.gotData放置{{gotData}}来显示index.html的值。

为什么我不能在控制器的其他位置访问$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>

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

为什么您无法在$scope.gotData 功能之外看到getData.success()的原因是因为.success() async ,当您尝试在.success()之外访问该值时,该值不可用。这实际上意味着承诺尚未得到解决。

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

watch放在$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 :(得分:0)

虽然不是最好的编程习惯,但解决方法是使用$ 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
   }]);