AngularJS: Call a particular function before any partial page controllers

angularjs, javascript

Solution

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.

Problem

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

Original source