【问题标题】:$rootScope in AngularJS stays UNDEFINED in Controller despite injection?尽管注入,AngularJS 中的 $rootScope 在控制器中仍保持未定义?
【发布时间】:2015-10-11 15:46:34
【问题描述】:

这是一个用于移动应用的小型 ionic / angularJS 项目。

我正在尝试读取与 index.html 位于同一文件夹中的 JSON 文件,然后将其分配给 RUN 段中的 $rootScope 变量,然后在控制器中检索 $rootScope 变量值。但是,尽管进行了服务注入等等,但它根本无法正常工作。

这是我的 JSON 文件:

    {"docs":[{"Name":"Alfreds Futterkiste","City":"Berlin","Country":"Germany"},
             {"Name":"Ana Trujillin Moreo","City":"México D.F.","Country":"Mexico"}
            ]
    }

这是我的 app.js / script.js:

angular.module('starter', ['ionic'])    
    .run(function($ionicPlatform, $rootScope, $http) {
      $ionicPlatform.ready(function() {
        $rootScope.myDocs = $http.get("/customers.json")
                                 .success(function (response) {
                                    return response.docs;
                                  });
      });
    })

    .controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
      $scope.myDocs = $rootScope.myDocs;
      //$scope.myDocs = [{'Name': 'a1'},{'Name': 'b1'},{'Name': 'c1'}];
      $scope.myStr = JSON.stringify($rootScope.myDocs);
    }])

这是我的 index.html 中的相关部分:

<body ng-app="starter">    
      <ion-pane>
        <ion-header-bar class="bar-stable">
          <h1 class="title">Ionic Blank Starter</h1>
        </ion-header-bar>
        <ion-content ng-controller="MyCtrl">
        <ion-list>
        <ion-item ng-repeat="x in myDocs">
        {{x.Name}}
        </ion-item>
        </ion-list>
        </ion-content>
      </ion-pane>
</body>

我在这里看到了其他类似的例子,但这仍然不起作用,我一直在用头撞墙来实现一个非常简单的事情。

非常感谢您的快速帮助。 这是 Plunker:http://plnkr.co/edit/zx9ANUzCYVvosZFiPSGY?p=info

【问题讨论】:

  • 欢迎来到 Stack Overflow!请务必查看游览:stackoverflow.com/tour。如果有任何答案解决了您的问题,请使用复选标记(它将变为绿色)将最有帮助的答案标记为“已接受”,以表达您的感激之情并帮助未来的访问者。

标签: angularjs controller ionic rootscope


【解决方案1】:

由于ionicPlatform.ready,您遇到了时间问题,并且您没有正确使用$http 承诺。

这是一种方法:

.run(function($rootScope, $http) {
  // $http returns a promise, not the value
  $rootScope.docPromise = $http.get("/customers.json")
    .then(function(response) {
      return response.docs;
    });
})

.controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
  // you get the value within a .then function on the promise
  $rootScope.docPromise.then(function(result) {
    $scope.myDocs = result;
  })
}])

您不太可能需要在 ionicPlatform.ready 内进行此 http 调用。如果您不需要,那么它只会拖延通话而没有任何好处。如果由于某种原因您确实需要在 ready 函数中进行调用,有很多方法可以解决这个问题。这是一个例子:

// inject $q service
var deferred = $q.defer();
$rootScope.docPromise = deferred.promise;
$ionicPlatform.ready(function() {
  $http.get(etc).then(function(response) {
    deferred.resolve(response.docs);
  });
});
// use $rootScope.docPromise as in the previous example

【讨论】:

  • 正是我要写的! +1 另外,我肯定会考虑使用路由器(ui-router)并在渲染视图之前解析为特定视图加载数据。
【解决方案2】:

您可能假设来自$http.get() 上的success 方法的返回值将分配给$rootScope 上的myDocs 属性,但事实并非如此。 $http.get() 是一个异步操作,一旦响应可用,就会调用成功回调。此外,您的成功回调的返回值也未分配,因为它发生在未来的某个时间。

您需要更新您的ready(),如下所示。

   $ionicPlatform.ready(function() {
     /* get will return a promise, cache it in on rootScope for use in controller*/
      $rootScope.httpPromise = $http.get("/customers.json");
   });

在您的控制器中

   .controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
      $rootScope.httpPromise.then(function(response){
           $scope.myDocs = response.data.docs;
       });
    }]);

【讨论】:

  • 这样做的缺点是你不知道什么时候会设置$rootScope.myDocs。 OP 可能期望 console.log($rootScope.myDocs) 在他的控制器中有值,但它不会。
  • @m59... 是的,我现在明白了这个问题。尽管我在成功回调中缓存了来自 http 调用的响应,但控制器可能会在调用完成之前被调用,这会再次返回 undefined。感谢您指出这一点。我更新了我的答案来处理这个:)
  • 您仍然遇到$ionicPlatform.ready 的异步问题。在执行控制器功能时,$rootScope.httpPromise 可能尚未分配。我的回答解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
  • 1970-01-01
相关资源
最近更新 更多