2016-04-30 72 views
1

我已經初始化我的應用程序下面這兩個指南:AngularJS +雲終端:裝載終端跨多個控制器API

我的設置看起來像這個:

個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。

當我們想要創建另一個控制器來處理我們應用程序的另一個視圖時,就會遇到挑戰。假設我們創建了一個ContentPageCtrl控制器 - 那麼我們是否需要再次啓動我們的端點服務?我們如何使端點服務可供所有控制器使用,而不必重複自己?

我哈克解決方案 爲了解決這個問題,我$watchthe 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 
       }); 
     } 
    }); 
}]); 

這意味着我需要$watchbackend_ready變量在我需要進行端點調用的每個控制器中。我的方法感覺很骯髒,並且存在擴展問題。

這有什麼更好的方法?

回答

2

更好的方法是利用Promises的力量。然後您可以將您的服務初始化爲一次(在服務功能中)以及您簡單地調用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 
});