Pawan Pawan - 1 month ago 6
Javascript Question

AngularJS: Call a particular function before any partial page controllers

I want to call a particular function:

GetSession()
at the beginning of my application load. This function makes a
$http
call and get a session token:
GlobalSessionToken
from the server. This session token is then used in other controllers logic and fetch data from the server. I have call this
GetSession()
in main controller:
MasterController
in
$routeChangeStart
event but as its an asynchronous call, my code moves ahead to
CustomerController
before the
$http
response.

Here is my code:

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);
});
}


And my HTML has following sections:

<body ng-app="myApp" ng-controller="MasterController">
<!--Placeholder for views-->
<div ng-view="">
</div>
</body>


How can I make sure this
GetSession()
is always called at the very beginning of my application start and before any other controller calls and also called only once.

EDIT: This is how I added
run
method as per Maxim's answer. Still need to figure out a way to wait till
$http
call returns before going ahead with controllers.

//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;
}

Answer

You can't postpone the initialisation of controllers.

You may put your controller code inside a Session promise callback:

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 ...
   } ); 
} );

Alternative: If you don't want to use such callbacks, you could have your session request synchronous, but that would be a terrible thing to do.

Comments