2

I need to perform an AJAX request against my API for authentication information before routing kicks in and routing data requests resolve (I'm using a server-to-server OpenID auth solution).

I initialize my app like this currently:

angular.module('mynamespace.admin', [
    'ngRoute',
    'ui.bootstrap',
    'mynamespace.directives',
    'mynamespace.filters',
    'mynamespace.factories',
    'mynamespace.resources',
    'mynamespace.admin.templates',
    'mynamespace.admin.forms'
]);

angular.module('mynamespace.admin').run(['$rootScope', '$http', 'base64', function($rootScope, $http, base64) {
    if (!window.location.origin) {
      window.location.origin = window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
    }

    // I NEED THIS TO FINISH BEFORE ROUTES RUN AND PERFORM
    // HTTP REQUESTS TO RESOLVE DATA
    $http.get(window.location.origin + '/account').success(function(accountData) {
        $rootScope.accountData = accountData;

        // Set up auth headers to be sent with every HTTP request.
        $http.defaults.headers.common = { 'Access-Control-Request-Headers': 'accept, origin, authorization' };
        $http.defaults.headers.common['Authorization'] = 'Basic ' + base64.encode(accountData.apiKey + ':' + accountData.apiPassword);
    });
}]);

angular.module('mynamespace.admin').config(['$routeProvider', function($routeProvider) {
    $routeProvider
        .when('/', {  // THIS IS RUNNING BEFORE THE $http REQUEST in .run() finishes
            redirectTo: '/forms'
        });
}]);

Routing kicks in at the .config() callback at the end. Unfortunately the /forms route contains routes with resolve items which end up making $http requests before I set up the common $http headers inside the .run() callback. Basically I have a race condition.

So, my question is: How can I execute and complete an AJAX request and ensure it returns BEFORE my app's routing kicks in and routes start making AJAX requests?

If this question is somehow unclear, I ask that you please request clarification, and I will clarify.

Chad Johnson
  • 21,215
  • 34
  • 109
  • 207
  • Wow. I said "If this question is somehow unclear, I ask that you please request clarification, and I will clarify" and someone STILL voted to close this. Some people just don't read. – Chad Johnson Nov 28 '14 at 21:25

2 Answers2

2

Use routeChangeStart event of angular.

var checkAuthentication = function(event, routeChange) {
    routeChange.$$route.resolve = {
        app: function($q) {
            var deferred = $q.defer();
            //Authentication({deferred.resolve();})
            return deferred.promise;
        }
    }
}

$rootScope.$on('$routeChangeStart', checkAuthenticationFn);
Saidh
  • 1,131
  • 1
  • 12
  • 21
  • 1
    Unfortunately an AJAX request made on $routeChangeStart may not complete before routing begins. – Chad Johnson Nov 28 '14 at 21:25
  • 1
    Need to use resolve method in such cases. Write the asynchronous calls in $$route.resolve. Also use defer method in Ajax call. – Saidh Dec 02 '14 at 03:46
  • You commented on this at exactly the right time...wow. I came back to work on this today just as you commented. I ended up using your idea combined with this: https://gist.github.com/davemo/5815716. I looped through $route.routes and added a resolve function to each which relied on a promise that only resolves once the AJAX request completes. – Chad Johnson Dec 02 '14 at 05:51
  • Hm, actually, adding the resolve to the next route in the $routeChangeStart event callback is nicer IMO than looping through the routes. Cool. Thanks man. – Chad Johnson Dec 02 '14 at 06:07
0

(Can't add a comment due to my reputation points, sry.) Try searching for the ".run" method of angular.module, maybe it helps you.

Here is an answer for the .run method: https://stackoverflow.com/a/20664122/2334204

--Edit--

Even the .config method runs before the .run method.

Community
  • 1
  • 1
DSalme
  • 61
  • 4