angular 通用和 ngIf 检查延迟 - Angular 9
Delays with angular universal and ngIf checks - Angular 9
我刚刚开始在现有应用程序中集成 angular universal,我注意到页面在一秒钟内呈现错误的布局,当页面完全加载时一切看起来都很好。
这是一个例子:
我在页面加载时获取登录状态,如下所示:
this.authService.isLoggedIn.subscribe(res => {
this.isLoggedIn = res;
});
并根据结果设置不同的布局(如果为真或为假):
<div *ngIf="isLoggedIn" class="user-logged">
// user logged in
</div>
<div *ngIf="!isLoggedIn" class="user-logged">
// user not logged in
</div>
但是当服务 returns 为真(这意味着用户已登录)时,我可以看到未登录状态一秒钟,然后页面加载并且一切正常。
所有 BreakpointObserver 检查也会发生这种情况。
更新 1:
这是我试过的:
我创建了一个 AppConfigService:
@Injectable()
export class AppConfigService {
private isLoggedStatus: boolean;
constructor(private authService: AuthService) { }
public isLoggedIn(): boolean {
return this.isLoggedStatus;
}
load() {
return new Promise((resolve, reject) => {
this.authService.isLoggedIn.subscribe(loggedInStatus => {
this.isLoggedStatus = loggedInStatus;
resolve(true);
});
});
}
}
在我的 AuthService 中:
private isLoginSubject = new BehaviorSubject<boolean>(this.isAuthenticated);
get isLoggedIn(): Observable<boolean> {
return this.isLoginSubject.asObservable();
}
get isAuthenticated(): boolean {
const token = this.getToken();
if (token) {
if (jwtHelper.isTokenExpired(token)) {
return false;
} else {
return true;
}
} else {
return false;
}
}
在我的app.module.ts
export function appConfigFactory(provider: AppConfigService) {
return () => provider.load();
}
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: appConfigFactory,
deps: [AppConfigService],
multi: true
}
]
我认为问题出在服务器端本地存储的使用上,但如果那是问题,我该如何检查用户是否已登录?
发生这种情况是因为,当您的应用首次评估 isLoggedIn
时,它是错误的(或未定义,这取决于您如何定义它)。
然后,当订阅事件 returns 数据时,isLoggedIn
值发生变化,因此您的 html 也会因您的 *ngIf
条件而发生变化。
如果您想在应用呈现之前加载 isLoggedIn
数据,您可以使用 APP_INITIALIZER
.
这篇 post 解释了如何使用它:https://www.cidean.com/blog/2019/initialize-data-before-angular-app-starts/
这个比较老,但也不错:https://devblog.dymel.pl/2017/10/17/angular-preload/
编辑
在您的 AppConfigService
中,isLoggedStatus
应该是一个 Observable,否则在 Promise 解析之前它将是未定义的(并且评估为 false)。
您应该等到 promise 结束后再呈现您的组件。
示例步骤:
- 显示登录页面。
- 当用户点击 登录 时,调用您的服务器并等待响应。
- 如果成功:
isLoggedStatus
= 真
- 保存会话(如果需要,在
LocalStorage
中)
- 显示您的组件(
isLoggedIn
为真)
- 如果失败:
isLoggedStatus
= 假
- 显示您的组件(
isLoggedIn
将为 false)
- 用户应该有机会重试登录
发生这种情况是因为您使用了 localStorage
。您应用程序的服务器端版本无法访问本地存储(就像它无法访问任何浏览器对象上的 window
、navigator
),因此它认为用户未连接。
使用 angular 通用和身份验证时,您可以使用服务器可以访问的 cookie。
有一些可用的库,但据我所知,它们还没有完全准备好与 angular 9:
一起使用
-
在 github issue.
中解决 angular 9
-
不适用于 angular 通用 github issue
我刚刚开始在现有应用程序中集成 angular universal,我注意到页面在一秒钟内呈现错误的布局,当页面完全加载时一切看起来都很好。
这是一个例子:
我在页面加载时获取登录状态,如下所示:
this.authService.isLoggedIn.subscribe(res => {
this.isLoggedIn = res;
});
并根据结果设置不同的布局(如果为真或为假):
<div *ngIf="isLoggedIn" class="user-logged">
// user logged in
</div>
<div *ngIf="!isLoggedIn" class="user-logged">
// user not logged in
</div>
但是当服务 returns 为真(这意味着用户已登录)时,我可以看到未登录状态一秒钟,然后页面加载并且一切正常。 所有 BreakpointObserver 检查也会发生这种情况。
更新 1: 这是我试过的: 我创建了一个 AppConfigService:
@Injectable()
export class AppConfigService {
private isLoggedStatus: boolean;
constructor(private authService: AuthService) { }
public isLoggedIn(): boolean {
return this.isLoggedStatus;
}
load() {
return new Promise((resolve, reject) => {
this.authService.isLoggedIn.subscribe(loggedInStatus => {
this.isLoggedStatus = loggedInStatus;
resolve(true);
});
});
}
}
在我的 AuthService 中:
private isLoginSubject = new BehaviorSubject<boolean>(this.isAuthenticated);
get isLoggedIn(): Observable<boolean> {
return this.isLoginSubject.asObservable();
}
get isAuthenticated(): boolean {
const token = this.getToken();
if (token) {
if (jwtHelper.isTokenExpired(token)) {
return false;
} else {
return true;
}
} else {
return false;
}
}
在我的app.module.ts
export function appConfigFactory(provider: AppConfigService) {
return () => provider.load();
}
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: appConfigFactory,
deps: [AppConfigService],
multi: true
}
]
我认为问题出在服务器端本地存储的使用上,但如果那是问题,我该如何检查用户是否已登录?
发生这种情况是因为,当您的应用首次评估 isLoggedIn
时,它是错误的(或未定义,这取决于您如何定义它)。
然后,当订阅事件 returns 数据时,isLoggedIn
值发生变化,因此您的 html 也会因您的 *ngIf
条件而发生变化。
如果您想在应用呈现之前加载 isLoggedIn
数据,您可以使用 APP_INITIALIZER
.
这篇 post 解释了如何使用它:https://www.cidean.com/blog/2019/initialize-data-before-angular-app-starts/
这个比较老,但也不错:https://devblog.dymel.pl/2017/10/17/angular-preload/
编辑
在您的 AppConfigService
中,isLoggedStatus
应该是一个 Observable,否则在 Promise 解析之前它将是未定义的(并且评估为 false)。
您应该等到 promise 结束后再呈现您的组件。
示例步骤:
- 显示登录页面。
- 当用户点击 登录 时,调用您的服务器并等待响应。
- 如果成功:
isLoggedStatus
= 真- 保存会话(如果需要,在
LocalStorage
中) - 显示您的组件(
isLoggedIn
为真)
- 如果失败:
isLoggedStatus
= 假- 显示您的组件(
isLoggedIn
将为 false) - 用户应该有机会重试登录
发生这种情况是因为您使用了 localStorage
。您应用程序的服务器端版本无法访问本地存储(就像它无法访问任何浏览器对象上的 window
、navigator
),因此它认为用户未连接。
使用 angular 通用和身份验证时,您可以使用服务器可以访问的 cookie。
有一些可用的库,但据我所知,它们还没有完全准备好与 angular 9:
一起使用-
在 github issue.
中解决 angular 9 -
不适用于 angular 通用 github issue