简体   繁体   中英

Angular2: canActivate

Currently I want to implement canActivate function, everything I want is to send a request to server each time page requested and get true/false in a json response in order to understand is user authenticated and permitted to review current page. And it seems that I completely stuck with observable and promise objects, which is new for me, what is what I have so far.

import { Injectable }     from '@angular/core';
import {CanActivate, Router}    from '@angular/router';
import { Http, Response } from '@angular/http';
import {Observable, Observer, Subject} from "rxjs/Rx";

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private router: Router, private http: Http) {}

    canActivate() {
        if (this.isAuthenticated()) {
            return true;
        } {
            this.router.navigate(['404']);
            return false;
        }
    }

    isAuthenticated() : Observable<boolean> {
        var subject = new Subject<boolean>();
        this.http.get("/index.php?module=Api&action=IsAuthenticated")
            .map((res : Response) => res.json())
            .subscribe(res => {
                console.log("next: returning true");
                subject.next(true);
            }, (res) => {
                console.log("next: returning false");
                subject.next(false);
            });
        return subject.asObservable().first();
    }
}

A few changes

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private router: Router, private http: Http) {}

    canActivate() {
        return this.isAuthenticated().first(); // not sure if `.first() is still necessary
    }

    isAuthenticated() : Observable<boolean> {
        return this.http.get("/index.php?module=Api&action=IsAuthenticated")
            .map((res : Response) => res.json())
            .catch(err => return Observable.of(false))
            .map(res => {
                return true
            });
    }
}

If isAuthenticated() does some async execution, we don't get true or false back, we get an Observable that emits a true or false value eventually

What we do is to return the observable we get from isAuthenticated()

In isAuthenticated with return the observable we get from this.http.get() and transform the emitted event. It seems the response from the server ( and transform the emitted event. It seems the response from the server ( res.json() ) is not used. Therefore we use ) is not used. Therefore we use catch() to return false in case of an error and true` otherwise.

Because the response from the server is not used .map((res : Response) => res.json()) could be omitted, except this is where you expect an error from that should case false to be returned. Also your production code might look different and require the response to be processed.

We don't subscribe anywhere, because this is what the router is doing when an Observable is returned from canActivate and if we call subscribe() we get a Subscription instead of an Observable .

canActivate can return either Observable<boolean> , Promise<boolean> or boolean .

As you are depending on asynchronous checking you cannot return a boolean.

It however looks like you could just simply do

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

I'm no expert on Observable yet, but it would also be easy for you to chain on a call to redirect if you where not authorised.

Here is the solution that works for me:

canActivate() {
    return this.http.get("/index.php?module=Api&action=IsAuthenticated")
        .toPromise()
        .then(this.extractData)
        .catch(this.handleError);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM