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。您应用程序的服务器端版本无法访问本地存储(就像它无法访问任何浏览器对象上的 windownavigator),因此它认为用户未连接。

使用 angular 通用和身份验证时,您可以使用服务器可以访问的 cookie。

有一些可用的库,但据我所知,它们还没有完全准备好与 angular 9:

一起使用