【问题标题】:Undefined Variable Inside Controller ($scope issue)控制器内部未定义变量($scope 问题)
【发布时间】:2026-02-02 05:55:01
【问题描述】:

所有,我在下面有以下 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>

【问题讨论】:

    标签: javascript angularjs http callback scope


    【解决方案1】:

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

    【讨论】:

    • 那么,这是否意味着一旦检索到数据,$scope.gotData 就被定义了?如果服务器响应相当快,那么我应该能够在调用 getData.success 之外通过 setTimeout(console.log($scope.gotData),1000) 来查看数据,对吧?
    • 是的..如果您使用 setTimeout(或 $timeout 服务,如果您想以更角度的方式做事),您将能够看到数据。 如果您在 1 秒(1000 毫秒)内获得数据
    【解决方案2】:

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

    此外,一旦 Angular 的摘要循环识别出 $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);
         })   
     }]);
    

    【讨论】:

    • 那么,只有当控制器调用getData.success 时,promise 才会被解析?我想了解“消化周期”和这些“承诺”($q)。你有很好的外行资源来了解 Angular 在后台做什么?
    • 嗯,是的。当 promise 被解决时,.success 被调用,当它被拒绝时,.error 被调用。你可以从这个link 中获得关于 Promise 的更好的想法。此外,thisthis 是开始使用 $q 的好地方。这是 $q 上的official docs
    • 我会读那些。我已经找到了官方文档,但是如果你没有计算机科学背景,Angular API 可能会非常不透明。我现在正在阅读$watch 服务。 This site 还不错。
    【解决方案3】:

    虽然不是最佳编程实践,但解决此问题的方法是使用 $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
       }]);

    【讨论】:

    • 谢谢,阿萨德。我将避免使用 $rootScope。这是在玩火。