Angular / Firebase-Guard在Firebase初始化完成之前运行

时间:2019-02-19 08:49:26

标签: angular typescript firebase angularfire2

在此处查看问题(打开控制台):

https://stackblitz.com/edit/angular-su5p89?file=src%2Fapp%2Fapp.module.ts

我已在initalizeApp中导入并调用了AppModule,如下所示:

import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFirestoreModule } from '@angular/fire/firestore';

@NgModule({
  imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),

    // Firebase
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    AngularFireAuthModule,

    // App
    AppRoutingModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [AppComponent]
})

export class AppModule {}

然后我创建了一个看起来像这样的警卫:

import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, CanLoad } from '@angular/router';
import * as firebase from 'firebase/app';

@Injectable({
  providedIn: 'root'
})

export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {

  /** @ignore */
  constructor() {}

  canLoad(): boolean {
    return this.performCheck();
  }

  canActivate(): boolean {
    return this.performCheck();
  }

  canActivateChild(): boolean {
    return this.performCheck();
  }

  private performCheck() {
    return !!firebase.auth().currentUser;
  }
}

并像这样使用它:

export const Routes = [
  {
    path: '',
    pathMatch: 'full',
    redirectTo: 'hello'
  },
  {
    path: 'hello',
    component: HelloComponent,
    canActivate: [AuthGuard]
  }
];

但是,这会产生以下错误:

  

ERROR错误:未捕获(承诺):[DEFAULT]:Firebase:无Firebase   应用“ [DEFAULT]”已创建-调用Firebase App.initializeApp()   (应用/无应用)。 [DEFAULT]:Firebase:没有Firebase应用“ [DEFAULT]”   已创建-调用Firebase App.initializeApp()(app / no-app)。       错误(index.cjs.js:361)       在应用程序上(index.cjs.js:244)       在Object.serviceNamespace [作为身份验证](index.cjs.js:302)       在AuthGuard.performCheck(auth.guard.ts:35)       在AuthGuard.canActivate(auth.guard.ts:29)       在评估时(check_guards.ts:121)       在Observable.eval [作为_subscribe](defer.ts:59)       在Observable._trySubscribe(Observable.ts:231)       在Observable.subscribe(Observable.ts:212)       在TakeOperator.call(take.ts:72)       在resolvePromise(zone.js:831)       在resolvePromise(zone.js:788)       在eval(zone.js:892)       在ZoneDelegate.invokeTask(zone.js:423)       在Object.onInvokeTask(ng_zone.ts:262)       在ZoneDelegate.invokeTask(zone.js:422)       在Zone.runTask(zone.js:195)       在排水微任务队列(zone.js:601)

在查看其他问题时,这表示该应用尚未初始化Firebase,这很奇怪,因为我在执行其他操作之前就已经这样做了。从理论上讲,警卫应该在之后运行,对吧?

我该如何解决?

1 个答案:

答案 0 :(得分:2)

由于某些原因,我会以不同的方式配置防护:

import * as firebase from 'firebase/app';

正在引起第二次初始化,并且没有调用initializeApp()方法会导致错误。

import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, CanLoad } from '@angular/router';
import { AngularFireAuth } from '@angular/fire/auth'; // instead of firebase
import { Observable } from 'rxjs';
import { take, map } from 'rxjs/operators'

@Injectable({
  providedIn: 'root'
})

export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {

  /** @ignore */
  constructor(private auth: AngularFireAuth) {}

  canLoad(): Observable<boolean> {
    return this.performCheck();
  }

  canActivate(): Observable<boolean> {
    return this.performCheck();
  }

  canActivateChild(): Observable<boolean> {
    return this.performCheck();
  }

  private performCheck(): Observable<boolean> {
    return this.auth.user.pipe(map((user) => {
      if (user) {
        // user is logged in
        return true;
      }
      // user is not logged in
      return false;
    }), 
    take(1));
  }
}

updated stackBlitz