2

Goal: In my application every controller should be initialized after a user has a session / is logged in, because in this controller I use the data of logged in user.

Code:

app.js

    app.run(function($q, $rootScope, AuthSvc){
    $rootScope.ajaxCall = $q.defer();
    AuthSvc.reloadSession().then(
        function(response){
            if(response!=null && response!=undefined){
                $rootScope.activeUserSession = response;
                $rootScope.ajaxCall.resolve();
            }else{
                $rootScope.activeUserSession = null;
                $rootScope.ajaxCall.reject();
            }
        });
    return $rootScope.ajaxCall.promise;
});

routes.js

.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/timeTracking', {
                templateUrl: 'partials/timeTracking/projectView.html',
                controller: 'timeTrackingController',
                resolve: {
                    response: function($rootScope, $q) {
                        var defer = $q.defer();
                        $rootScope.ajaxCall.promise.then(
                            function(){
                                defer.resolve();
                                return defer.promise;
                            });
                    }
                }
            }).

Problem: Controller gets initialized sometimes before the user has a session, I do not understand why.

Sorry I am new to Angular and my english is also crap, so I hope nevertheless you can understand what is my problem.

1 Answer 1

1

I think placing your session reload into the app.run is not the right place. Add it directly to resolve and checkout the docs for $q to learn how promises are working.

Because you can't call a promise or defer. You need to call a function that's returning a promise then you can add your then method to do your stuff after the promise is resolved.

Please have a look at the demo below or here at jsfiddle.

It's just an asynchronous method with $timeout to simulate the auth because I don't have a backend to add in the demo.

You can add your AuthSvc directly into resolve.

angular.module('demoApp', ['ngRoute'])
.controller('timeTrackingController', function($scope, response) {
    $scope.data = response;
})
.factory('authService', function($q, $timeout) {
    return {
        reloadSession: function() {
            var deferred = $q.defer();
            $timeout(function() {
                // just simulate session reload
                // real api would to the job here
                console.log('resolved defer now!!');
                deferred.resolve({dummyData: 'hello from service'});                
            }, 1000);
            
            return deferred.promise;
        }
    }
})
.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/timeTracking', {
                templateUrl: 'partials/timeTracking/projectView.html',
                controller: 'timeTrackingController',
                resolve: {
                    response: function(authService) {
                        return authService.reloadSession().then(function(data) {
                            return data;
                        })
                    }
                }
            })
        .otherwise('/timeTracking');
    }]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular-route.js"></script>

<div ng-app="demoApp">
    <script type="text/ng-template" id="partials/timeTracking/projectView.html">
        project view: {{data | json}}
    </script>
    <div ng-view=""></div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

thank you very much. It is a good Idea, but now in this case I call every time reloadSession, if I change a view. I can adjust the reloadSession function, so it will work fine (ask everytime if there is already a session). Why I tried to call this function in app.run, because it should only be called once (first call or reload of the appliation, but not after changing every view).
You could cache the promise to avoid doing new resolve at every view change. You can write it by yourself or use something like angular-promise-cache. I haven't tried promise cache but there is also some code where you can see how you could do caching.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.