[英]AngularJS: Call a particular function before any partial page controllers
我想在我的應用程序加載開始時調用一個特定的函數: GetSession()
。 此函數進行$http
調用並從服務器獲取會話令牌: GlobalSessionToken
。 然后,此會話令牌將用於其他控制器邏輯,並從服務器獲取數據。 我在主控制器中調用了這個GetSession()
: $routeChangeStart
事件中的MasterController
但是作為一個異步調用,我的代碼在$http
響應之前向前移動到CustomerController
。
這是我的代碼:
var GlobalSessionToken = ''; //will get from server later
//Define an angular module for our app
var myApp = angular.module('myApp', ['ngRoute']);
//Define Routing for app
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/customer', {
templateUrl: 'partials/customer.html',
controller: 'CustomerController',
resolve: {
loadData: function($q){
return LoadData2($q,'home');
}
}
}).
otherwise({
redirectTo: '/home'
});
}]);
//controllers start here and are defined in their each JS file
var controllers = {};
//only master controller is defined in app.js, rest are in separate js files
controllers.MasterController = function($rootScope, $http){
$rootScope.$on('$routeChangeStart', function(){
if(GlobalSessionToken == ''){
GetSession();
}
console.log('START');
$rootScope.loadingView = true;
});
$rootScope.$on('$routeChangeError', function(){
console.log('ERROR');
$rootScope.loadingView = false;
});
};
controllers.CustomerController = function ($scope) {
if(GlobalSessionToken != ''){
//do something
}
}
//adding the controllers to myApp angularjs app
myApp.controller(controllers);
//controllers end here
function GetSession(){
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
}).error(function (data, status, headers, config) {
console.log(data);
});
}
我的HTML有以下部分:
<body ng-app="myApp" ng-controller="MasterController">
<!--Placeholder for views-->
<div ng-view="">
</div>
</body>
我怎樣才能確保在應用程序啟動的最開始和任何其他控制器調用之前始終調用此GetSession()
,並且只調用一次。
編輯:這是我根據Maxim的答案添加run
方法的方法。 在繼續使用控制器之前,還需要找出等待$http
調用返回的方法。
//Some initializing code before Angular invokes controllers
myApp.run(['$rootScope','$http', '$q', function($rootScope, $http, $q) {
return GetSession($http, $q);
}]);
function GetSession($http, $q){
var defer = $q.defer();
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
defer.resolve('done');
}).error(function (data, status, headers, config) {
console.log(data);
defer.reject();
});
return defer.promise;
}
雖然這里的一些解決方案完全有效,但在我看來,路由定義的resolve
屬性是可行的方法。 在session.then
中編寫你的應用程序邏輯在每個控制器中有點太多了,我們在其中一個項目中也使用了這樣的方法,但是我沒有那么好用。
最有效的方法是使用resolve
來延遲控制器的實例化,因為它是一個內置的解決方案。 唯一的問題是你必須為每個路由定義添加類似代碼的resolve
屬性,這會導致代碼重復。
要解決此問題,您可以在輔助函數中修改路由定義對象,如下所示:
function withSession(routeConfig) {
routeConfig.resolve = routeConfig.resolve || {};
routeConfig.resolve.session = ['getSessionPromise', function(getSessionPromise) {
return getSessionPromise();
}]
return routeConfig;
}
然后,在這里定義你的路線:
$routeProvider.when('/example', withSession({
templateUrl: 'views/example.html',
controller: 'ExampleCtrl'
}));
這是我嘗試過並且最喜歡的眾多解決方案之一,因為它干凈且干燥。
你不能推遲控制器的初始化。
您可以將控制器代碼放在Session promise回調中:
myApp.factory( 'session', function GetSession($http, $q){
var defer = $q.defer();
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
defer.resolve('done');
}).error(function (data, status, headers, config) {
console.log(data);
defer.reject();
});
return defer.promise;
} );
myApp.controller( 'ctrl', function($scope,session) {
session.then( function() {
//$scope.whatever ...
} );
} );
替代方案 :如果您不想使用此類回調,則可以使您的會話請求同步,但這將是一件非常糟糕的事情。
您尚未提供與GetSession相關的任何詳細信息。 對於這樣的場景,您應該在$routeProvider
定義路由時使用resolve
屬性。 我看到你已經使用了resolve
。
您現在可以做的是將GlobalSessionToken
包裝到像GlobalSessionTokenService
這樣的Angular服務中,並在解析中調用它以在路由加載之前獲取令牌。 喜歡
resolve: {
loadData: function($q){
return LoadData2($q,'home');
},
GlobalSessionToken: function(GlobalSessionTokenService) {
return GlobalSessionTokenService.getToken() //This should return promise
}
}
然后可以在控制器中注入
controllers.MasterController = function($rootScope, $http,GlobalSessionToken){
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.