2016-07-25 5 views
0

Ich versuche, eine HTTP-Service-Methode aufrufen und schließlich eine Fehlermeldung zurück, aber nach einer Woche des Ausprobierens vieler Dinge (Promises, Observables, ...) kann ich ' t es zur Arbeit bringen. Ich hoffe, dass mir jemand helfen kann?Angular2 Call-Login-Funktion vom Dienst in der Komponente und Fehler zurück

Ich bin ein wenig neu bei Angular2 und arbeite alleine an diesem Projekt, mit niemandem sonst mit angularem Fachwissen. Ich habe einen 3-tägigen Trainingskurs bekommen.

Komponente

@Component({ 
    templateUrl: 'build/pages/login/login.html' 
}) 
export class LoginPage { 
    error: string; 

    constructor(private navController: NavController, private auth: AuthService) { 
    } 

    private login(credentials) { 
    // Method calling the login service 
    // Could return an error, or nothing 
    this.error = this.auth.login(credentials); 

    // If there is no error and the user is set, go to other page 
    // This check is executed before previous login methode is finished... 
    if (!this.error && this.auth.user) { 
     this.navController.setRoot(OverviewPage); 
    } 
    } 
} 

AuthService

@Injectable() 
export class AuthService { 
    private LOGIN_URL: string = "http://localhost:8080/rest/auth"; 
    private USER_URL: string = "http://localhost:8080/rest/user"; 

    private contentHeader: Headers = new Headers({ 
    "Content-Type": "application/json" 
    }); 

    errorMessage: string; 
    user: User; 

    constructor(private http: Http) { 
    } 

    login(credentials) { 
     let contentHeader = new Headers({ 
     "Content-Type": "application/json" 
     }); 

    this.http.post(this.LOGIN_URL, JSON.stringify(credentials), { headers: contentHeader }) 
     .map(res => res.json()) 
     .catch(this.handleError) 
     .subscribe(
     data => this.handleLogin(data), 
     err => this.handleError 
    ); 

    // could return an errorMessage or nothing/null 
    return this.errorMessage; 
    } 

    private handleLogin(data) { 
    let token = data.token; 
    this.getAccount(token); 
    } 

    private getAccount(token) { 
    let authHeader = new Headers({ 
     "Content-Type": "application/json", 
     "X-Auth-Token": token 
    }); 

    this.http.get(this.USER_URL, { headers: authHeader }) 
     .map(res => res.json()) 
     .catch(this.handleError) 
     .subscribe(
     data => this.setUser(data), 
     err => this.errorMessage = err 
    ); 
    } 

    private setUser(data) { 
    this.user = new User(data.naam, data.voornaam); 
    } 

    private handleError(error) { 
    // this.errorMessage is not saved? 

    if (error.status === 401) { 
     this.errorMessage = '401'; 
    } else if (error.status === 404) { 
     this.errorMessage = '404'; 
    } else { 
     this.errorMessage = 'Server error'; 
    } 

    return Observable.throw(error.json() || 'Server error'); 
    } 
} 

Antwort

1

Ich denke, Ihr Problem ist, dass Ihre Login-Methode einen flachen Wert (errorMessage) zurückkehrt. Da die Login-Methode eine asynchrone Anfrage macht, dass der Wert nicht initialisiert wird, wird immer Null zurückgegeben. Wenn ich das einrichten würde, würde ich die Login-Methode eine Observable zurückgeben.

Um die Dinge ein wenig komplizierter zu machen, scheint es, dass Sie nach dem Login einen weiteren Anruf tätigen möchten, um den angemeldeten Benutzer zu erreichen. Wenn Sie nicht möchten, dass Ihre Anmeldemethode ausgegeben wird, bis Sie beide Anrufe abgeschlossen haben, müssen Sie sie irgendwie kombinieren. Ich denke switch kann dies tun.

@Injectable() 
export class AuthService { 
    private LOGIN_URL: string = "http://localhost:8080/rest/auth"; 
    private USER_URL: string = "http://localhost:8080/rest/user"; 

    private contentHeader: Headers = new Headers({ 
    "Content-Type": "application/json" 
    }); 

    user: User; 

    constructor(private http: Http) { 
    } 

    login(credentials) { 
     let contentHeader = new Headers({ 
     "Content-Type": "application/json" 
     }); 

     let response:Observable<Response> = this.http.post(this.LOGIN_URL, JSON.stringify(credentials), { headers: contentHeader }); 

     //Take response and turn it into either a JSON object or 
     //a string error. 
     //This is an Observable<any> (any is returned by json()) 
     let jsonResponse = response.map(res => res.json()) 
           .catch(err => this.handleError(err)); 
     //Take JSON object and turn it into an Observable of whatever the 
     //login request returns 
     //This is an Observable<Observable<any>> (Observable<any> is returned 
     //by handleLogin 
     let userResponse = jsonResponse.map(
     data => this.handleLogin(data) 
    ); 

     //Switch to the observable of the login request 
     //This is an Observable<any>, we will switch to the Observable<any> 
     //returned by handleLogin 
     let finalResponse = userResponse.switch(); 

     //Hide actual response value from user. This will return an 
     //observable that will emit null on success and an error message 
     //on error 
     //Again, an Observable<any> since we're mapping to null 
     return finalResponse.map(res => null); 
    } 

    //We need to return this call as an observable so we can wire it into 
    //our chain 
    private handleLogin(data) { 
    let token = data.token; 
    return this.getAccount(token); 
    } 

    private getAccount(token) { 
    let authHeader = new Headers({ 
     "Content-Type": "application/json", 
     "X-Auth-Token": token 
    }); 

    let loginResponse = this.http.get(this.USER_URL, { headers: authHeader }) 
           .map(res => res.json()) 
           .catch((err) => this.handleError(err)); 

     loginResponse.subscribe(
     data => this.setUser(data) 
    ); 

     return loginResponse; 
    } 

    private setUser(data) { 
    this.user = new User(data.naam, data.voornaam); 
    } 

    private handleError(error) { 
    let errorMessage = "Uninitialized"; 
    if (error.status === 401) { 
     errorMessage = '401'; 
    } else if (error.status === 404) { 
     errorMessage = '404'; 
    } else { 
     errorMessage = error.json() || 'Server error'; 
    } 
    return Observable.throw(errorMessage); 
    } 
} 

Jetzt in Ihrer Login-Komponente müssen Sie asynchron auf die Antwort hören. Dies wird nicht sofort passieren (wahrscheinlich ziemlich schnell mit localhost, aber kann in der realen Welt eine Weile dauern), also habe ich ein loginDisabled hinzugefügt, das verhindern kann, dass der Benutzer zweimal auf die Login-Schaltfläche klickt, während er auf die Login-Anfrage wartet Zu erfüllen.

Keine Versprechungen das ist alles korrekt (ich habe nichts, um es zu testen), aber es sollte die richtige allgemeine Richtung sein.

+0

Vielen Dank für Ihre Antwort! Es ist genau das, was ich gesucht und wie ein Charme gearbeitet habe! Und ein großes Dankeschön für die Ausarbeitung der Observables und die Kommentare, es macht mir so viel klarer, was genau Happing ist. Kleine Lösung für Menschen, die den gleichen Code verwenden möchten: 'beobachtbare ' 'sollte beobachtbare ' und 'data => this.handleLogin (Daten) sein; ';'' ohne sein sollte 'data => this.handleLogin (Daten)' – Stijn