#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
, чтобы перевести его в стабильное состояние (: немного странная настройка (может даже изменить ее), но пока работает. Что-то вроде этого кода .