AngularJS仅在父控制器完成异步调用时加载控制器

时间:2013-12-07 11:29:18

标签: 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,每个页面都有一个控制器,每个页面都有一个由$ routeprovider管理的自己的控制器

main.js

.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进行异步调用才能使会话看起来像这样。

gapi.client.myapi.app.init().execute(function(resp){});

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

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

});

ExampleCtrl

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,这对于用户预期来说看起来不太好。

我尝试在$ routeProvider中使用解析并从那里执行API调用,但是然后我的MainCtrl没有正确获取会话值。

我的解决方案是做一个:

   $routeProvider.when('/example', {
templateUrl : 'partials/example.html', 
controller  : 'ExampleCtrl',
access      : accessLevels.PUBLIC,
    resolve     : MainCtrl.init
}

但$ routeProvider

中没有MainCtrl

另一个想法是拦截ng-view调用,但我不知道在哪里这样做并且可以同时访问服务。

感谢您的任何想法/帮助

修改

我试着在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;
                }]

        });

如果我希望每个子控制器调用api,哪个有效。我想要的是让子控制器使用MainCtrl准备好后初始化的任何东西。基本上只在MainCtrl准备就绪时加载视图和相关的控制器(包括异步调用

1 个答案:

答案 0 :(得分:6)

根据以下评论进行编辑

这个想法是用ng-if阻止视图,直到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> 

旧答案: 您是否可以将对Google的异步调用移至服务并让该服务返回承诺

     myApp.service('DataService', ['$rootScope', '$http', function ($rootScope, $http) {

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

在您的路由设置中,有一个解决方案,等待在Google服务调用返回后唯一加载控制器

    when('/example', {templateUrl: 'partials/example.html', 
                   controller: 'ExampleCtrl', 
         resolve: {
            'MyServiceData': function (DataService) {
                return DataService.promise;
            }
        }}).

编辑:看看如何返回api通话的承诺https://stackoverflow.com/a/16117041/514463