模板在承诺完成之前呈现

时间:2019-07-17 18:58:08

标签: javascript angular firebase promise firebase-authentication

我正在尝试使用Firebase为网站实施持久签名会话。我相信我已经正确地完成了所有操作,除了当用户重新加载页面时,身份验证令牌都可用,但是因为我的函数fetchAuthTokenOnReload()里面有一个诺言(我相信这就是问题所在),仅在浏览器已经呈现我的HTML之后,promise才会被解决。我知道这一点是因为重新加载后,我最初已经退出,但是只要单击诸如导致重新渲染的随机按钮之类的东西,我就会登录。

这很奇怪,因为我没有在Observables中遇到这个问题。我试着四处寻找如何处理承诺以及如何或如何将Promises转换为Observable,但没有成功。在承诺完成后,我还尝试重新路由用户,因为这将导致重新渲染,但没有用。 也很奇怪,因为我的firebase.auth()。signInWithEmailAndPassword(email,password)函数也使用了promise,但是在对int签名后我没有问题。

感谢您的帮助。

auth.service.ts

import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { Subject } from 'rxjs';
import { ConfirmationModalService } from '../confirmation-modal/confirmation-modal.service';

@Injectable()
export class AuthService {

  token: String;
  tokenChanged = new Subject<String>();

  constructor(
    private router: Router,
    private confirmationModalService: ConfirmationModalService) { }

  signInUser(email: string, password: string) {
    firebase
      .auth()
      .setPersistence(firebase.auth.Auth.Persistence.LOCAL)
      .then(() => {
        return firebase.auth().signInWithEmailAndPassword(email, password)
          .then( // also uses a promise but no problems here
            response => {
              this.router.navigate(['/']);
              firebase.auth().currentUser.getIdToken()
                .then(
                  (token: string) => {
                    this.token = token;
                    this.tokenChanged.next(token);
                  }
                );
            }
          )
          .catch(
            error => {
              console.log(error);
              this.confirmationModalService.displayConfirmationModal('invalid username/password', 'failure', 2000);
            }
          );
      }).catch(error => {
        console.log(error);
      });
  }

  setAuthToken(token: String) {
    console.log('setting auth token');
    this.token = token;
    this.tokenChanged.next(token);
    console.log('set autToken');
  }

  getAuthToken() {
    return this.token;
  }

  fetchAuthTokenOnReload() {
    console.log('fetchAuthTokenOnReload()');
    firebase.auth().onAuthStateChanged((user) => {
      console.log(this.token);
      if (user) {
        console.log('already signed in');
        console.log('currently authToken = user.getIdToken()');
        return user.getIdToken()
          .then((token) => {
            this.setAuthToken(token);
          })
          .catch((error) => {
            console.log(error);
          });
      } else {
        console.log('not signed in');
        console.log(user);
        return null;
      }
    });
  }

  logout() {
    firebase.auth().signOut();
    this.token = null;
    this.tokenChanged.next(null);
    window.location.reload();
  }


**app.component.ts**


    import { Component, OnInit } from '@angular/core';
    import { Router, NavigationEnd } from '@angular/router';
    import * as firebase from 'firebase';
    import { AuthService } from './auth/auth.service';
    import { AngularFireStorage } from 'angularfire2/storage';

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })

    export class AppComponent implements OnInit {

      token: String;
      isAuthenticated: boolean;

      constructor(
        private router: Router,
        private authService: AuthService,
        private afStorage: AngularFireStorage) {
        this.router.events.subscribe(event => {
          if (event instanceof NavigationEnd) {
            (<any>window).ga('set', 'page', event.urlAfterRedirects);
            (<any>window).ga('send', 'pageview');
          }
        });
      }

      ngOnInit() {
        this.authTokenChanged();
        this.authService.fetchAuthTokenOnReload();
      }

      // When the pages has finished loading, this.token has the correct value but the browser uses the previous value, which is undefined at the time

      authTokenChanged() {
        console.log('inside observable authTokenChaned()');
        console.log('authTokenChanged() - before change');
        console.log(this.token);
        this.authService.tokenChanged.subscribe(
          (token) => {
            this.token = token;
            console.log('authTokenChanged() - after change');
            console.log(this.token);
            this.router.navigate(['/']);
          }
        );
      }
    }

app.component.html

<div *ngIf="token">
  <div class="auth-status-bar logged-in">YOU ARE LOGGED IN</div>
</div>

<app-confirmation-modal></app-confirmation-modal>
<div class="container-fluid row">
  <div class="col-xs-12" [ngStyle]="{ 'margin-top': token ? '30px' : '0px' }">
    <app-header></app-header>
    <router-outlet></router-outlet>
    <router-outlet name='opportunities'></router-outlet>
    <app-footer></app-footer>
  </div>
</div>

应该发生的是:重新加载页面后,该div:

<div *ngIf="token">
  <div class="auth-status-bar logged-in">YOU ARE LOGGED IN</div>
</div>

应该显示。

1 个答案:

答案 0 :(得分:0)

请尝试使用BehaviorSubject而不是使用tokenChanged处的Subject,因为Subject不保留该值,这就是为什么您将其作为null的原因。