javascript - AngularJS ui router $stateChangeStart with promise inifinite loop -
i'm trying build sort of authentication in angular app , redirect external url when user not logged in (based on $http.get).
somehow end in infinite loop when event.preventdefault() first line in $statechangestart.
i've seen multiple issues answers on stackoverflow, saying "place event.preventdefault() before state.go in else". controllers fired , page shown before promise returned.
even when put event.preventdefault() in else, odd happens:
going root url, automatically adds /#/ after url , $statechangestart fired multiple times.
app.js run part:
.run(['$rootscope', '$window', '$state', 'authentication', function ($rootscope, $window, $state, authentication) { $rootscope.$on('$statechangestart', function (event, tostate, toparams) { event.preventdefault(); authentication.identity() .then(function (identity) { if (!authentication.isauthenticated()) { $window.location.href = 'external url'; return; } else { $state.go(tostate, toparams); } }); }); }]);
authentication.factory.js identity() function:
function getidentity() { if (_identity) { _authenticated = true; deferred.resolve(_identity); return deferred.promise; } return $http.get('url') .then(function (identity) { _authenticated = true; _identity = identity; return _identity; }, function () { _authenticated = false; }); }
edit: added states:
$stateprovider .state('site', { url: '', abstract: true, views: { 'feeds': { templateurl: 'partials/feeds.html', controller: 'userfeedscontroller userfeedsctrl' } }, resolve: ['$window', 'authentication', function ($window, authentication) { authentication.identity() .then(function (identity) { if (!authentication.isauthenticated()) { $window.location.href = 'external url'; } }) }] }) .state('site.start', { url: '/', views: { 'container@': { templateurl: 'partials/start.html' } } }) .state('site.itemlist', { url: '/feed/{feedid}', views: { 'container@': { templateurl: 'partials/item-list.html', controller: 'itemlistcontroller itemlistctrl' } } }) .state('site.itemdetails', { url: '/items/{itemid}', views: { 'container@': { templateurl: 'partials/item-details.html', controller: 'itemscontroller itemsctrl' } } }) }])
if need more info, or more pieces of code app.js let me know !
$statechangestart
not wait promise resolved before exiting. way make state wait promise use resolve
within state's options.
.config(function($stateprovider) { $stateprovider.state('home', { url: '/', resolve: { auth: function($window, authentication) { return authentication.identity().then(function (identity) { if (!authentication.isauthenticated()) { $window.location.href = 'external url'; } }); } } }); });
by returning promise function, ui-router won't initialize state until promise resolved.
if have other or children states need wait this, you'll need inject auth
in.
from wiki:
the resolve keys must injected child states if want wait promises resolved before instantiating children.
Comments
Post a Comment