Функция Angular2 canActivate (), вызывающая функцию async

Я пытаюсь использовать охранники маршрутизатора Angular2, чтобы ограничить доступ к некоторым страницам в моем приложении. Я использую Firebase Authentication. Чтобы проверить, вошел ли пользователь в систему Firebase, я должен вызвать .subscribe() в объекте FirebaseAuth с обратным вызовом. Это код охранника:

 import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { AngularFireAuth } from "angularfire2/angularfire2"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Rx"; @Injectable() export class AuthGuard implements CanActivate { constructor(private auth: AngularFireAuth, private router: Router) {} canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable|boolean { this.auth.subscribe((auth) => { if (auth) { console.log('authenticated'); return true; } console.log('not authenticated'); this.router.navigateByUrl('/login'); return false; }); } } 

Когда вы переходите на страницу с защитой, на нее печатается либо authenticated , либо not authenticated (после некоторой задержки, ожидающей ответа от firebase). Однако навигация никогда не завершается. Кроме того, если я не вошел в систему, я перенаправлен на маршрут /login . Итак, проблема, с которой я столкнулась, – return true , не отображает запрошенную страницу пользователю. Я предполагаю, что это потому, что я использую обратный вызов, но я не могу понять, как это сделать в противном случае. Есть предположения?

canActivate необходимо вернуть Observable который завершает:

 @Injectable() export class AuthGuard implements CanActivate { constructor(private auth: AngularFireAuth, private router: Router) {} canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable|boolean { return this.auth.map((auth) => { if (auth) { console.log('authenticated'); return true; } console.log('not authenticated'); this.router.navigateByUrl('/login'); return false; }).first(); // this might not be necessary - ensure `first` is imported if you use it } } 

Отсутствует return и я использую map() вместо subscribe() потому что subscribe() возвращает Subscription не Observable

canActivate может возвращать Promise которое также разрешает boolean

Вы можете использовать Observable для обработки логической части async. Вот код, который я тестирую, например:

 import { Injectable } from '@angular/core'; import { CanActivate } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { DetailService } from './detail.service'; @Injectable() export class DetailGuard implements CanActivate { constructor( private detailService: DetailService ) {} public canActivate(): boolean|Observable { if (this.detailService.tempData) { return true; } else { console.log('loading...'); return new Observable((observer) => { setTimeout(() => { console.log('done!'); this.detailService.tempData = [1, 2, 3]; observer.next(true); observer.complete(); }, 1000 * 5); }); } } } 

Чтобы расширить самый популярный ответ. API Auth для AngularFire2 имеет некоторые изменения. Это новая подпись для достижения AngularFire2 AuthGuard:

 import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { AngularFireAuth } from 'angularfire2/auth'; import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; @Injectable() export class AuthGuardService implements CanActivate { constructor( private auth: AngularFireAuth, private router : Router ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable|boolean { return this.auth.authState.map(User => { return (User) ? true : false; }); } } 

Примечание. Это довольно наивный тест. Вы можете заблокировать журнал экземпляра User, чтобы узнать, хотите ли вы протестировать его с более подробным аспектом пользователя. Но, по крайней мере, нужно защищать маршруты от пользователей, которые не вошли в систему.

Вы можете вернуть true | false в качестве обещания.

 import {Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router'; import {Observable} from 'rxjs'; import {AuthService} from "../services/authorization.service"; @Injectable() export class AuthGuard implements CanActivate { constructor(private router: Router, private authService:AuthService) { } canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean { return new Promise((resolve, reject) => { this.authService.getAccessRights().then((response) => { let result = response; let url = state.url.substr(1,state.url.length); if(url == 'getDepartment'){ if(result.getDepartment){ resolve(true); } else { this.router.navigate(['login']); resolve(false); } } }) }) } } в import {Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router'; import {Observable} from 'rxjs'; import {AuthService} from "../services/authorization.service"; @Injectable() export class AuthGuard implements CanActivate { constructor(private router: Router, private authService:AuthService) { } canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean { return new Promise((resolve, reject) => { this.authService.getAccessRights().then((response) => { let result = response; let url = state.url.substr(1,state.url.length); if(url == 'getDepartment'){ if(result.getDepartment){ resolve(true); } else { this.router.navigate(['login']); resolve(false); } } }) }) } } 
  • Угловой маршрутизатор поддерживает строку запроса
  • Страница обновления Angular2 router.navigate обновить
  • Как использовать HashLocationStrategy с виджем Auth0 Lock для входа пользователя
  • Angular2: Сделать дорожки нечувствительными к регистру
  • Угловое 2: получение RouteParams из родительского компонента
  • Маршрут Angular 2's Router нарушен при использовании маршрутов HTML5?
  • Давайте будем гением компьютера.