延迟角度通用和ngIf检查-角度9

时间:2020-03-18 09:29:12

标签: angular 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>

但是当服务返回true(这意味着用户已登录)时,有一秒钟,我可以看到未登录状态,然后页面就会加载,并且一切正常。 所有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
    }
]

我认为问题出在服务器端使用本地存储,但是如果那是问题,我该如何检查用户是否已登录?

2 个答案:

答案 0 :(得分:1)

发生这种情况是因为,当您的应用首次评估isLoggedIn时,它为假(或未定义,取决于您如何定义它)。

然后,当订阅事件返回数据时,isLoggedIn的值将更改,因此,由于*ngIf的情况,您的html也将更改。

如果您想在应用渲染之前加载isLoggedIn数据,则可以使用APP_INITIALIZER

这篇文章解释了如何使用它:https://www.cidean.com/blog/2019/initialize-data-before-angular-app-starts/

这个人年龄较大,但也很不错:https://devblog.dymel.pl/2017/10/17/angular-preload/

编辑

在您的AppConfigService中,isLoggedStatus应该是可观察的,否则在Promise解决之前,它将是未定义的(并且评估为false)。

您应该等待,直到承诺结束,再渲染您的组件。

示例步骤:

  • 显示登录页面。
  • 当用户点击登录时,请致电您的服务器并等待响应。
  • 如果成功:
    • isLoggedStatus =
    • 保存会话(如果需要,可以保存在LocalStorage中)
    • 显示您的组件(并且isLoggedIn为真)
  • 如果失败:
    • isLoggedStatus = 错误
    • 显示您的组件(并且isLoggedIn为假)
    • 用户应有机会重试登录

答案 1 :(得分:1)

发生这种情况是因为您使用了localStorage。应用的服务器端版本无法访问本地存储(就像它无法访问任何浏览器对象上的windownavigator)一样,因此它认为用户未连接。

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

有一些可用的库,但是从我看来,它们还没有完全可以在角度9中使用: