【发布时间】:2022-07-01 20:26:45
【问题描述】:
如何在 NgRx 中等待 Effect 的完成。 我被困在这种情况下。我有一个效果,即从存储中加载一个令牌,并根据是否找到令牌来分派一个更新 Store 的操作。
autoLogin$ = createEffect(() => this.actions$.pipe(
ofType(AuthActions.startAutoLogin),
switchMap(action => {
return from(AuthUtils.getTokenFromStorage(USER_TOKEN_STORAGE_KEY));
}),
switchMap(token => {
if (AuthUtils.isProvidedTokenNotExpired(token)) {
return from(AuthUtils.getTokenData(token));
}
return EMPTY;
}),
map(tokenData => {
if (tokenData) {
return AuthActions.autoLogin({payload: tokenData});
}
})
));
动作AuthActions.autoLogin({payload: tokenData})被调度并用于更新商店中的一个字段:
export interface AuthState {
isLoggedIn: boolean,
}
最后我在 Router Guard 中使用该字段来检查用户是否登录:
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanLoad, CanActivate {
constructor(private router: Router,
private store: Store<fromAuth.AuthState>) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.store.select(AuthSelectors.selectIsLoggedIn).pipe(
tap(isLoggedId => {
if (!isLoggedId) {
this.router.navigateByUrl('/login').then();
}
}),
);
}
}
问题是:
Router Guard 在 Effect 之前执行,Store 更新太晚,用户被重定向到登录页面。当我查看重定向后商店的状态时,isLoggedIn 是true。
Router Guard 是否可以等待 Effect 执行重定向结束?
【问题讨论】:
-
并非如此。诀窍是在那里使用一个额外的键(如加载:true | false),您可以使用相同的(成功)操作进行交换。然后在你的守卫中,你可以将加载的选择器切换到登录的选择器。那有意义吗?不过要小心,使用选择器作为守卫可能会很棘手,因为它们最初总是在存储中发出当前值(可能为 null 或未定义。
-
谢谢你的建议,我试试。我可以使用 Guard 内部 Effect 中定义的逻辑,但我不想在那里加载令牌。关于 Guard 中的选择器,第一个是
false,这就是为什么我每次都会重定向 -
False 只有在加载为真时才是真正的值。这有点诀窍。
-
如果发出的值始终为 false,它并不能解决我的问题
-
为什么会是……?你必须确保你在守卫中的 observable 只在加载为真时才发出。您可以对此进行过滤。
标签: angular ngrx ngrx-store ngrx-effects angular-router-guards