Angular2,Firebase,AngularFire2,路由防范以及如何处理订阅

时间:2016-10-12 05:51:41

标签: angular firebase firebase-authentication angularfire2

我有一个现在有效的路线保护,但我收到了这条消息:

WARNING: the getAuth() API has changed behavior since adding support for Firebase 3.
    This will return null for the initial value when the page loads, even if the user is actually logged in.
    Please observe the actual authState asynchronously by subscribing to the auth service: af.auth.subscribe().
    The getAuth method will be removed in future releases

这是我目前的警卫:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire, FirebaseListObservable, AuthProviders, AuthMethods } from 'angularfire2';
import {Observable} from "rxjs/Rx";

@Injectable()
export class AuthFirebaseGuard implements CanActivate {

  user={}
  constructor(public af: AngularFire,
              private router: Router
              ) {}

  canActivate(route: ActivatedRouteSnapshot,
              state: RouterStateSnapshot){

    if (this.af.auth.getAuth().uid){
        return true;
    } else {
        this.router.navigate(['login']);
        return false;
    }

  }
}

以下是我想要改变的内容:

@Injectable()
export class AuthFirebaseGuard implements CanActivate {

  user={}
  constructor(public af: AngularFire,
              private router: Router
              ) {}

  canActivate(route: ActivatedRouteSnapshot,
              state: RouterStateSnapshot){


    this.user = this.af.auth.subscribe(user => {
              if (user) {
                        this.user = user.auth.providerData[0];
                        if (user.auth.emailVerified==false){
                        user.auth.sendEmailVerification().then(function() {
                            this.router.navigate(['login']);
                            return false;
                        });
                        } else {
                           return true;
                        }
              }
              else {
                this.router.navigate(['login']);
                return false;
              }
            }); 
  }
}

如何等待订阅完成?

Class 'AuthFirebaseGuard' incorrectly implements interface 'CanActivate'.
  Types of property 'canActivate' are incompatible.
    Type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => void' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable<boolean> | Pr...'.
      Type 'void' is not assignable to type 'boolean | Observable<boolean> | Promise<boolean>'.








ERROR in [default] /Users/Documents/frontend/iboot/src/app/common/auth-firebase.gaurd.ts:14:13 
Class 'AuthFirebaseGuard' incorrectly implements interface 'CanActivate'.
  Types of property 'canActivate' are incompatible.
    Type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => Observable<{}>' is not assignable to type '(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => boolean | Observable<boolean> | Pr...'.
      Type 'Observable<{}>' is not assignable to type 'boolean | Observable<boolean> | Promise<boolean>'.
        Type 'Observable<{}>' is not assignable to type 'Promise<boolean>'.
          Property 'then' is missing in type 'Observable<{}>'.

ERROR in [default] /Users/Documents/frontend/iboot/src/app/common/auth-firebase.gaurd.ts:41:40 
Argument of type 'firebase.Promise<any>' is not assignable to parameter of type 'Promise<any>'.
  Types of property 'then' are incompatible.
    Type '(onResolve?: (a: any) => any, onReject?: (a: Error) => any) => Promise<any>' is not assignable to type '{ <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected:...'.
      Type 'firebase.Promise<any>' is not assignable to type 'Promise<any>'.

1 个答案:

答案 0 :(得分:4)

canActivate可以返回一个布尔值,一个promise或一个observable,因此你可以使用AngularFire2的auth observable来构造一个observable:

canActivate(
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
) {

  return this.af.auth

    // Observables returned by canActivate have to complete, so take the
    // first emitted value from the auth observable.

    .first()

    // Use mergeMap to project the values emitted from the inner
    // observables created using Observable.fromPromise and
    // Observable.of. (If you weren't making the call to
    // sendEmailVerification, you could just use the map operator
    // and would return a boolean.)

    .mergeMap((user) => {

      if (user && user.auth) {
        if (!user.auth.emailVerified) {
          return Observable.fromPromise(user.auth
            .sendEmailVerification()
            .then(() => {
              this.router.navigate(['login']);
              return false;
            })
          );
        }
        return Observable.of(true);
      } else {
        this.router.navigate(['login']);
        return Observable.of(false);
      }
    });
}