web-dev-qa-db-fra.com

Attendre http dans Guard sur Angular 5

J'utilise un Guard sur une application Angular pour résoudre les données critiques initiales. Sur la version 4 de Angular, je le traitais comme ceci:

// app.routing.ts
routing = [{
    path: '', component: AppComponent, canActivate: [ResolveGuard],
}];

// resolve.guard.ts
@Injectable()
export class ResolveGuard implements CanActivate {
    constructor(
        private _api: ApiService,
    ) { }

    canActivate(): any {
        return this._api.apiGet('my/url').map(response) => {
            if ( response.status === 'success') {
                // Consume data here
                return true;
            }

            return false;
        }).first();
    }
}

Puisque la nouvelle version de Http sur Angular 5 n’utilise plus la propriété .map(), cela ne fonctionne pas.

Si je change .map() en .subscribe(), aucune erreur ne sera renvoyée, mais l'application ne sera jamais résolue correctement. D'autre part, l'utilisation de .first() et/ou .map() génère des erreurs, comme prévu dans cette version.

Que dois-je faire dans ce cas?

Je n'ai besoin d'activer cette route que si et quand les données initiales sont chargées.


Modifier pour ajouter des informations sur la fonction apiGet:

constructor(private _http: HttpClient) {}

public apiGet(url: string): any {
    return this._http
        .get(this.apiUrl + url)
        .catch(this.handleError.bind(this));
}
4
celsomtrindade

Donc, tout d’abord, évitez d’utiliser any lorsque cela est possible, surtout lorsque vous savez quel type appartient à quel endroit.

export interface FooInterface {
  status: string;
  fooString : string;
  fooNumber : number;
}

Dans un premier temps, je vais définir l’interface du service de manière propre, puis je vais reformuler la classe de garde.

RÉPONSE MISE À JOUR for rxjs 6.x

import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class FooService {
   constructor(private _http: HttpClient) {}

   public apiGet(url: string): Observable<FooInterface> {
    return this._http
        .get<FooInterface>(this.apiUrl + url)
        .pipe(
          catchError(error => {
             // do general error handling if necessary and throw
            throwError(error);
           })
        );
  }
}

La classe de garde:

import { of, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
    private fooService: FooService ,
) { }

canActivate(): Observable<boolean> {
    return this.fooService.apiGet('my/url')
       .pipe(
         map(response => response.status === 'success'),
         catchError(error => of(false))
       );
}

RÉPONSE ORIGINALE pour rxjs 5.x

import { _throw } from 'rxjs/observable/throw':

constructor(private _http: HttpClient) {}

public apiGet(url: string): Observable<FooInterface> {
    return this._http
        .get<FooInterface>(this.apiUrl + url)
        .catch(error => {
          // do general error handling if necessary and throw
          _throw(error);
       });
}

La classe de garde:

import { of } from 'rxjs/observable/of';

@Injectable()
export class ResolveGuard implements CanActivate {
constructor(
    private _api: ApiService,
) { }

canActivate(): Observable<boolean> {
    return this._api.apiGet('my/url')
       .map(response => {
          let val = false;
          if ( response.status === 'success') {
                // Consume data here
                val = true;
          }
          return val;
        }).catch(error => {
          // consume the error maybe?
          of(false)
        });
}
12
Jota.Toledo

il suffit d'importer l'opérateur map et cela fonctionnera:

import { Observable } "rxjs/Observable"; 
import "rxjs/add/operator/map"; 

 canActivate(): Observable<boolean>{
        return this._api.apiGet('my/url').map(response => {
            if ( response.status === 'success') {
                // Consume data here
                return true;
            }
            return false;
        });
    }