Search code examples
angulartypescriptangular-promiseoidc-client-jsoidc-client

Promisse in constructor don't finish before method runs in angular 10


promise from oidc-client in angular 10 constructor is taking too long to resolve, the isLoggedIn function is being called before the constructor places de value in the user variable.

this is my code:

import { UserManager, UserManagerSettings, User } from 'oidc-client';

export class AuthService {
  private user: User = null;
  private manager = new UserManager(getClientSettings());
  privatecachedRequests: Array<HttpRequest<any>> = [];

  constructor() {
    this.manager.getUser().then(user => {
      this.user = user;
    });
  }
  isLoggedIn(): boolean {
    return this.user != null && !this.user.expired; <= this.user is null because the constructor did not finished the async part
  }

this code was working in angular 8

when I called getUser() function inside my isLoggedIn method, it worked, but i would like to use this from the constructor


Solution

  • Use Rxjs Subject to act as a proxy.

    import {Subject } from 'rxjs',<-- add this
    export class AuthService {
      private user: User = null;
      private manager = new UserManager(getClientSettings());
      privatecachedRequests: Array<HttpRequest<any>> = [];
      private loginSubject= new Subject()<-- add this line
    
      constructor() {
        this.manager.getUser().then(user => {
          this.user = user;
          if(this.user != null && !this.user.expired)
           {
             this.loginSubject.next(true)
           } else{
               this.loginSubject.next(false)
              }
         
        });
      }
      isLoggedIn(): Observable<boolean> {
         return this.loginSubject.asObservbale();<-- avoid leak 
      }
    

    you can return Observable in canActivate

    import { Injectable } from '@angular/core';
    import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
    import { Observable } from 'rxjs/Observable';
    import {map} from 'rxjs/operators';
    
    
    @Injectable()
    export class AuthGuard implements CanActivate {
    
      constructor(private authService:AuthService, private router: Router) { }
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>  {
        return this.authService.isLoggedIn().pipe(
          map(res => {
            if (res) {
              return true;
            } else {
              this.router.navigate(['/login']);
               return false
            }
          })
      }   
    
    }