Наблюдаемая защита маршрутизатора Angular 2 v3 с ngrx

#angular #angular2-routing #ngrx #angular2-router3

#angular #angular2-маршрутизация #ngrx #angular2-router3

Вопрос:

Я пытаюсь создать «приложение аутентификации» с помощью redux (ngrx), и я пытаюсь использовать свое состояние приложения в секретной охране. Здесь вы можете увидеть мой github: https://github.com/tamasfoldi/ngrx-auth/tree/router Вот как выглядит мой охранник:

 @Injectable()
export class SecretGuard implements CanActivate {
  constructor(private store: Store<AppState>, private router: Router) {
  }
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.store.let(getLoginState())
      .map(state$ => state$.isLoggedIn)
  }
}
  

Он возвращается с атрибутом isLoggedIn, который должен быть в порядке, потому что маршрутизатор разрешает promises и observable, но маршрутизатор блокирует его, когда я перехожу к секретной части. Вот мои маршруты:

 export const appRoutes: Routes = [
  {
    path: '',
    redirectTo: 'auth',
    pathMatch: 'full'
  },
  {
    path: 'auth',
    children: [
      { path: '', redirectTo: 'login', pathMatch: 'full' },
      { path: 'login', component: LoginComponent },
      { path: 'register', component: RegisterComponent }
    ]
  },
  {
    path: 'secret',
    canActivate: [SecretGuard],
    children: [
      { path: '', redirectTo: 'default', pathMatch: 'full' },
      { path: 'default', component: DefaultSecretComponent }
    ]
  }
];
  

В redux я получаю состояние инициализации, поэтому я также попытался пропустить первое излучение в моем наблюдаемом, но это не работает.
Вот код пропуска:

 @Injectable()
export class SecretGuard implements CanActivate {
  constructor(private store: Store<AppState>, private router: Router) {
  }
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.store.let(getLoginState())
      .skip(1)
      .map(state$ => state$.isLoggedIn)
  }
}
  

Если я использую функцию аутентификации моего AuthService, она работает правильно, но это решение не является «redux-подобным». Можете ли вы помочь мне с этим, как заставить его работать с ngrx? Или я не могу использовать свое состояние приложения в guards?

Ответ №1:

Вы можете синхронно получать значение из хранилища, не нужно «передавать все» (:

https://github.com/ngrx/store#getstate-getvalue-and-value

 import 'rxjs/add/operator/take';

function getState(store: Store<State>): State {
    let state: State;
    store.take(1).subscribe(s => state = s);
    return state;
}

@Injectable()
export class SecretGuard implements CanActivate {
  constructor(private store: Store<AppState>, private router: Router) { }

  canActivate():boolean {
    return getState(this.store).login.isLoggedIn;
  }
}
  

Комментарии:

1. Спасибо, он работает, но если я добавлю к нему некоторую логику обработки ошибок (перенаправление на аутентификацию в случае сбоя защиты) Я перенаправляюсь на страницу авторизации. Я думаю, это связано с тем, что свойство isLoggedIn начального состояния равно false . Если я пропущу (1), это нормально при перезагрузке, но не работает при попытке навигации с панели навигации, потому что он пропускает каждый первый. У вас есть идеи, как это решить?

2. Он работает, если я использую debounceTime, но не уверен, что это лучшее решение

3. У меня не было этой проблемы, потому что я рано решил иметь два редуктора — auth и user . Я использую auth только для true / false / pending и user для данных профиля пользователя, затем использую auth в guards и user в компонентах для перенаправления. Это несколько больше работы во время входа / выхода из системы — я отправляю LoginUserAction и LoginAuthAction , но с ним легче справиться позже. Я ожидаю, что это будет полезно и для отложенной загрузки, я могу упаковать auth в AppModule и «user» в AdminModule

4. Хм, спасибо. Я попробую. Звучит лучше. Какое начальное значение для auth ожидающего или ложного? Если у вас нет проблемы с начальным значением, я думаю, что она находится на рассмотрении, и вы не перенаправляете, пока она не станет «стабильной» (true или false). Я прав?

5. На самом деле я использую null , true , false и "pending" и setTimeout , чтобы перевести его в стабильное состояние (: немного странная настройка (может даже изменить ее), но пока работает. Что-то вроде этого кода .