user3287019
user3287019

Reputation: 321

AngularJS load controller after resolve doesn't work

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.

Upvotes: 2

Views: 2271

Answers (1)

AWolf
AWolf

Reputation: 8970

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>

Upvotes: 1

Related Questions