Shodan4004
Shodan4004

Reputation: 57

ionic/angular service.subscribe fired regardless

I am writing the login section for my Ionic app and I'm having a problem with getTokenAsObservable.subscribe().

Basically, when the token is saved (clicked Login button) or deleted (clicked Logout button) the subscribe checks the status of the token. In case it is not present it moves to the login page. In case it is present it runs a check API to see if the user's account has permissions.

Everything works, the only problem is that when on the app start the body of the function this.tokenService.getTokenAsObservable().subscribe() is executed for some reason even if the Ionic Storage has not been created yet and therefore the token will always be empty. It results in the fact that even if one has already logged in, the app will show the login page for 1 second and then afterwards move to the home page.

HomePage class:

      ngOnInit(){
        
        this.tokenService.getTokenAsObservable().subscribe(
          token => {
            this.token = token
            if(this.token){
              this.checkLogin()
            } else {
              this.router.navigate(['/login'])
            }
          }
        );
        this.initFirebase()
      }
    
      async checkLogin(){
        await this.checkUserApi();
    
        if (this.response !== "Permission granted!") {
          this.router.navigate(['/login']);
        } else if (this.token && this.response === "Permission granted!") {
          this.loadData();
          this.router.navigate(['/']);
        }
      }  
    
      async checkUserApi(): Promise<void> {
        try {
          const response = await fetch('https://****.it/accounts/check-state', {
            headers: { 'Authorization': this.token },
            method: 'GET'
          });
          const data = await response.json();
          this.response = data.description;
        } catch (error) {
          throw error;
        }
      }

TokenService class:

    export class TokenService {
    
      private tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>('');
    
      constructor(private storage: Storage) { 
        this.storage.create().then(() => {
          this.init();
        });
      }
    
      async init() {
        const token = await this.storage.get('jwtToken');
        this.tokenSubject.next(token);
      }
    
      async saveToken(token: string): Promise<void> {
        await this.storage.set('jwtToken', token);
        this.tokenSubject.next(token);
      }
    
      async removeToken(): Promise<void> {
        await this.storage.remove('jwtToken');
        console.log("Token remove, removeToken func")
        this.tokenSubject.next('');
      }
    
      getTokenAsObservable(): Observable<string> {
        return this.tokenSubject.asObservable();
      }
    }

------------------- EDIT ------------

I kinda found a solution butIi would still like to hear from someone better than me.

HomePage class:

    ngOnInit(){
    this.tokenService.init().then(()=> {
        this.tokenService.getTokenAsObservable().subscribe(
          token => {
            this.token = token
            console.log("Token received in subscribe function")
            if(this.token){
              this.checkLogin()
            } else {
              this.router.navigate(['/login'])
            }
          }
    }

TokenService class:

      async init() {
        this.storage.create()
        const token = await this.storage.get('jwtToken');
        this.tokenSubject.next(token);
      }

Basically I executed this.tokenService.getTokenAsObservable().subscribe() only after the this.tokenService.init() has completed.

Upvotes: 0

Views: 60

Answers (1)

Shodan4004
Shodan4004

Reputation: 57

   ngOnInit(){
    this.tokenService.init().then(()=> {
        this.tokenService.getTokenAsObservable().subscribe(
          token => {
            this.token = token
            console.log("Token received in subscribe function")
            if(this.token){
              this.checkLogin()
            } else {
              this.router.navigate(['/login'])
            }
          }
    }
      async init() {
    const token = await this.storage.get('jwtToken');
    this.tokenSubject.next(token);
  }

Fixed by subscribing only after the token.service been initialize

Upvotes: 0

Related Questions