AngularJS 仅在父 Controller 完成异步调用时加载 Controller

标签 angularjs google-cloud-endpoints

我正在使用 AngularJS 和 Google Cloudendpoint 构建一个网站

架构如下。我有 :

1 - 管理整个站点显示的 MainCtrl(顶部菜单、模态等...)

<body ng-controller="MainCtrl" ng-cloak main-directive>
    ...
    <div ng-view></div>
    ...
</body>

2 - ng-view,每个页面都有一个 Controller ,每个页面都有一个由 $routeprovider 管理的自己的 Controller

主文件
.config([
    '$routeProvider',
    '$locationProvider', 
    '$httpProvider',
    function($routeProvider, $locationProvider, $httpProvider) {

                    ...
        $routeProvider.when('/example', {
            templateUrl : 'partials/example.html', 
            controller  : 'ExampleCtrl',
            access      : accessLevels.PUBLIC
                    }
                    ...
        $routeProvider.otherwise({redirectTo: '/'});
    }

MainCtrl 需要对 Google Cloud Endpoint 进行异步调用,以使 session 看起来像这样。
gapi.client.myapi.app.init().execute(function(resp){});

到目前为止,我所做的是将该代码包装在 MainCtrl 调用的 Service 函数中,然后在每个子 Controller 中监视 initDone 值,当异步调用完成时,该值会在 MainCtrl 中更新。

主控件
SessionService.init().then(function(data){
    $scope.initDone = SessionService.getInitDone();
});

服务
angular.module('myapp.services').service('SessionService', function ($http, $q, $rootScope) {

this.initDone = false
this.session = {}

this.init = function(){
    var s = this; 
    var deferred = $q.defer();
    gapi.client.myapi.app.init().execute(function(resp){
        deferred.resolve(resp);
        s.initDone = true;
    });
    return deferred.promise;
}

this.getInitDone = function(){
    return this.initDone;
}

});

示例控件
angular.module('myapp.controllers').controller('ExampleCtrl', function MainCtrl($scope, $timeout, $log, $location, SessionService) {

$scope.$watch('initDone', function(newVal, oldVal){
    $scope.testValue = SessionService.getInitDone()
})

});

虽然这项工作我不确定它是正确的解决方案。我想要的是能够让 ng-view 等待 MainCtrl 完成他的工作。

因为按照我的方式做这意味着一旦对端点的调用得到更新,ng-view 就会显示出来,从用户的 Angular 来看,这看起来不太好。

我尝试使用 $routeProvider 中的解析并从那里进行 API 调用,但随后我的 MainCtrl 无法正确获取 session 值。

我的解决方案是做一个:
   $routeProvider.when('/example', {
templateUrl : 'partials/example.html', 
controller  : 'ExampleCtrl',
access      : accessLevels.PUBLIC,
    resolve     : MainCtrl.init
}

但是 MainCtrl 在 $routeProvider 中不可用

另一个想法是拦截 ng-view 调用,但我不确定在哪里执行此操作并同时访问 Service。

感谢您的任何想法/帮助

编辑

我试图在我的 main.js 中做这样的事情
        $routeProvider.when('/example', {
            templateUrl : 'partials/example.html', 
            controller  : 'ExampleCtrl',
            access      : accessLevels.PUBLIC,

            resolve: {
                sessionData: ["$q", "SessionService", function($q, SessionService) {
                    //console.log(SessionService.getTest())

                    var deferred = $q.defer();
                    gapi.client.myapi.app.init().execute(function(resp){
                        deferred.resolve(resp);
                    });
                    return deferred.promise;
                }]

        });

如果我希望每个子 Controller 都调用 api,这会起作用。我想要的是让子 Controller 在 MainCtrl 准备好后使用它初始化的任何东西。基本上只在 MainCtrl 准备好时才加载 View 和关联的 Controller (包括异步调用

最佳答案

根据以下评论编辑

这个想法是用 ng-if 阻止 View ,直到 api 调用返回:

// Session service
 this.init = function(){
      if (!this.initDone){
          var s = this;
          var deferred = $q.defer();
          gapi.client.myapi.app.init().execute(function(resp){
              deferred.resolve(resp);
              s.initDone = true;
          });
          return deferred.promise;
      }
 }




// MainController.js :
 $scope.initDone = false;
 SessionService.init().then(function(
     $scope.initDone = SessionService.getInitDone();
  });


// index.html: 
<div ng-if="initDone"> 
    <div id="view" ng-view> </div>
</div> 

旧答案:
你能把对谷歌的异步调用移到一个服务上,让那个服务返回一个 promise 吗?
     myApp.service('DataService', ['$rootScope', '$http', function ($rootScope, $http) {

     var promise = $http.get("http://google.com/theservice").success(function (data) {
             ......
      });
      this.promise = promise

在您的路由设置中,然后有一个解析,它将等待在对 Google 服务的调用返回后才加载 Controller
    when('/example', {templateUrl: 'partials/example.html', 
                   controller: 'ExampleCtrl', 
         resolve: {
            'MyServiceData': function (DataService) {
                return DataService.promise;
            }
        }}).

编辑:在这里查看如何返回 api 调用的 promise https://stackoverflow.com/a/16117041/514463

关于AngularJS 仅在父 Controller 完成异步调用时加载 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20440816/

相关文章:

javascript - ng-model 未从 Controller 更新到 View

java - 在 Google Cloud Endpoints 中获取原始 HTTP 数据( header 、Cookie 等)

java - 使用 curl 将数据发布到本地主机的 HTTP Post 方法失败

javascript - 承载授权,来自服务器的 400 错误

javascript - 如何在 AngularJS 的单个页面中添加多个 Controller

javascript - ionic 平台 ng-show 只是第二次工作

javascript - Angular js 在单页上使用 $this 多个 Controller

python - 如何返回动态 json 作为来自谷歌云端点 python 的响应

java - 如何将自定义对象传递到应用程序引擎端点

java - google app engine 支持 Java 的 restful API?