AngularJS + Cloud Endpoints: загрузка 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
). Вот что происходит в нашем коде:
- Клиент gapi загружается, затем вызывает
init()
, который вызываетwindow.loadCloudEndpoints()
cloudendpoints.init(postInit)
загружает службу конечной точки cloudendpoints, которая затем вызываетpostInit()
Перезвоните. Затем мы можем сделать вызовы API оконечных точек изpostInit()
,
Проблема возникает, когда мы хотим создать еще один контроллер для обработки другого представления нашего приложения. Допустим, мы создаем ContentPageCtrl
контроллер - нужно ли нам снова запускать нашу службу конечных точек? Как мы можем сделать службу конечной точки доступной для всех контроллеров, не повторяя себя?
Мое хакерское решение Чтобы обойти это, я $watch
the backend_ready
так что я могу начать делать гэппи-вызовы только после загрузки конечных точек API:
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
переменная в каждом контроллере, в котором мне нужно сделать вызовы конечной точки. Мой подход кажется довольно грязным и имеет проблемы с масштабированием.
Каков лучший подход к этому?
1 ответ
Лучшим подходом к этому было бы использование силы Promises
, затем вы можете получить свой Service init один раз (внутри сервисной функции) и для каждого метода, который вы просто вызываете 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
});