Путают $locationChangeSuccess и $stateChangeStart

Я пытаюсь выполнить некоторую аутентификацию с помощью AngularUI Router. $urlRouter.sync() выглядит точно, что мне нужно. Тем не менее, это доступно только при перехвате $locationChangeSuccess. Но когда я это делаю, $state.current.name пуст, тогда как я хочу, чтобы оно было текущим состоянием.

Здесь мой код:

$rootScope.$on('$locationChangeSuccess', function(event, next, nextParams) {
  event.preventDefault();
  if ($state.current.name === 'login') {
    return userService.isAuthenticated().then(function(response) {
      var authenticated;
      authenticated = response.authenticated;
      return alert(authenticated);
    });
  }
});

Любые указания относительно того, что я делаю неправильно?

Ответ 1

Я предлагаю пойти больше "UI-Router way". Мы должны использовать событие $rootScope.$on('$stateChangeStart', где $state.current будет надлежащим образом предоставлено. Вот рабочий пример

Пусть наблюдается простое (но не наивное) решение, которое может быть продолжено до любой степени позже. Также, если вам понравится этот подход, здесь представлена ​​более полная реализация: angular аутентификация входа в систему ui-router

Во-первых, пусть наша пользовательская служба определяется следующим образом:

.factory('userService', function ($timeout, $q) {

    var user = undefined;

    return {
        // async way how to load user from Server API
        getAuthObject: function () {
            var deferred = $q.defer();

            // later we can use this quick way -
            // - once user is already loaded
            if (user) {
                return $q.when(user);
            }

            // server fake call, in action would be $http
            $timeout(function () {
                // server returned UN authenticated user
                user = {isAuthenticated: false };
                // here resolved after 500ms
                deferred.resolve(user)
            }, 500)

            return deferred.promise;
        },

        // sync, quick way how to check IS authenticated...
        isAuthenticated: function () {
            return user !== undefined
                && user.isAuthenticated;
        }
    };    
})

Итак, мы используем async (здесь $timeout) для загрузки объекта user. В нашем примере у него будет свойство {isAuthenticated: false }, которое будет использоваться для проверки подлинности.

Существует также метод синхронизации isAuthenticated(), который, пока пользователь не будет загружен и не разрешен, всегда возвращает false.

И это будет наш слушатель события '$stateChangeStart':

.run(['$rootScope', '$state', 'userService',
 function ($rootScope, $state, userService) {

     $rootScope.$on('$stateChangeStart', function (event, toState,   toParams
                                                        , fromState, fromParams) {    
        // if already authenticated...
        var isAuthenticated = userService.isAuthenticated();
        // any public action is allowed
        var isPublicAction = angular.isObject(toState.data)
                           && toState.data.isPublic === true;    

        if (isPublicAction || isAuthenticated) {
          return;
        }

        // stop state change
        event.preventDefault();

        // async load user 
        userService
           .getAuthObject()
           .then(function (user) {

              var isAuthenticated = user.isAuthenticated === true;

              if (isAuthenticated) {
                // let continue, use is allowed
                $state.go(toState, toParams)
                return;
              }    
              // log on / sign in...
              $state.go("login");
           })
       ...

Сначала мы проверяем, является ли пользователь уже загружен и аутентифицирован (var isAuthenticated = ...). Затем мы дадим зеленый любой общедоступный метод. Это делается с помощью свойства data {} определения объекта состояния (см. Прикрепить пользовательские данные к объектам состояния)

И что это. В случае состояний, определенных как в приведенном ниже фрагменте, мы можем испытать:

  • 'public', 'home' разрешены кому-либо
  • 'private', 'private' будет перенаправлен на логин, если isAuthenticated === false
  • 'login' в этом примере обеспечивает быстрый способ переключения isAuthenticated on/off

    // States
    $stateProvider
    
      // public
      .state('home', {
          url: "/home",
          templateUrl: 'tpl.html',
          data: { isPublic: true },
      })
      .state('public', {
          url: "/public",
          templateUrl: 'tpl.html',
          data: { isPublic: true },
      })
      // private
      .state('private', {
          url: "/private",
          templateUrl: 'tpl.html',
      })
      .state('private2', {
          url: "/private2",
          templateUrl: 'tpl.html',
      })
    
      // login
      .state('login', {
          url: "/login",
          templateUrl: 'tpl.html',
          data: { isPublic: true },
          controller: 'loginCtrl',
      })
    

Убедитесь, что все здесь

Некоторые другие ресурсы: