簡體   English   中英

AngularJS:在任何部分頁面控制器之前調用特定函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM