【问题标题】:AngularJS + Cloud Endpoints: loading endpoints api across multiple controllersAngularJS + Cloud Endpoints:跨多个控制器加载端点 api
【发布时间】:2016-08-25 07:06:51
【问题描述】:

我已经按照这两个指南初始化了我的应用程序:

我的设置如下所示:

app.js

function init() {
    console.log('running global init()');
    window.initgapi();
}

var app = angular.module('app', []);

// Main Controller
app.controller('MainCtrl', ['$scope', '$window', 'cloudendpoints', function($scope, $window, cloudendpoints) {

    // this is called once eventapi is loaded
    var postInit = function() {
        $scope.backend_ready = true;
        $scope.fetchContent();
    };

    $window.initgapi = function() {
        cloudendpoints.init(postInit);
    };

    $scope.fetchContent = function() {
        gapi.client.cloudendpoints
            .getContent()
            .execute(function(resp) {
                // do something with response
            });
    };

}]);

cloudendpoints 服务在它自己的文件中,cloudendpoints.js

// for loading endpoints service
app.factory('cloudendpoints', [function cloudendpoints() {
    var init = function(postInit) {
        var restUrl = '//' + window.location.host + '/_ah/api';
        gapi.client.load('cloudendpoints', 'v1', postInit, restUrl);
    };
    return { init: init };
}]);

最后,我们的脚本按以下顺序加载:

<script src="angular.min.js"></script>
<script src="app.js"></script>
<script src="controllers/mainCtrl.js"></script>
<script src="services/cloudendpoints.js"></script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>    

挑战 到目前为止效果很好,因为我们只使用一个控制器 (MainCtrl)。这就是我们的代码中发生的事情:

  1. gapi 客户端加载,然后调用init(),后者调用window.loadCloudEndpoints()
  2. cloudendpoints.init(postInit) 加载 cloudendpoints 端点服务,然后调用 postInit() 回调。然后,我们可以从 postInit() 中调用端点 API。

当我们想要创建另一个控制器来处理我们应用程序的另一个视图时,挑战就出现了。假设我们创建了一个ContentPageCtrlcontroller——然后我们需要再次初始化我们的端点服务吗?我们如何才能使端点服务对所有控制器都可用,而不必重复自己?

我的黑客解决方案 为了解决这个问题,我$watch the backend_ready 以便我只能在端点 api 加载后开始进行 gapi 调用:

 app.controller('ContentPageCtrl', ['$scope', function($scope) {

    /**
     * Make sure that the backend is ready before
     *   running any gapi.client.cloudendpoints calls
     **/
    $scope.$watch('backend_ready', function() {
        if ($scope.backend_ready === true) {
            gapi.client.cloudendpoints
                .loadContent()
                .execute(function(resp) {
                    // put content in DOM
                });
        }
    });
 }]);

这意味着我需要在需要进行端点调用的每个控制器中 $watch backend_ready 变量。我的方法感觉很脏,并且在扩展方面存在问题。

什么是更好的方法?

【问题讨论】:

    标签: angularjs google-app-engine google-cloud-endpoints google-api-js-client


    【解决方案1】:

    更好的方法是利用Promises 的力量。然后,您可以让您的 Service init once (在服务函数内部),并且在每个方法上您只需调用 promise.then(...) 并保持特定于该方法的逻辑。以此为例:

    app.factory('cloudendpoints', ['$q','$timeout','$window',function cloudendpoints($q,$timeout,$window) {
    
    var backend_ready = $q.defer();
    
    checkLoaded();
    function checkLoaded(){
     if($window.gapi)
      backend_ready.resolve();
     else
      $timeout(checkLoaded,100); //check again in 100ms
    }
    
    var init = function(postInit) {
        var restUrl = '//' + window.location.host + '/_ah/api';
        return backend_ready.promise.then(function(resp){
         gapi.client.load('cloudendpoints', 'v1', postInit, restUrl);
        }); //we are returning a promise so we can have more
            //flexability inside the controllers (do stuff after the loaded api);
    };
    return { 
     init: init
    };
    }]);
    
    
    
    
    //Somewhere inside a controller...
    app.controller('someCtrl', ['cloudendpoints', function(cloudendpoints){
     function postInit(){ ... }
    
    
      cloudendpoints.init(postInit); //waits for gapi to load, then executes init
    });
    

    【讨论】:

      猜你喜欢
      • 2014-09-16
      • 1970-01-01
      • 2021-06-02
      • 2012-10-18
      • 2014-10-23
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多