2016-12-19 3 views
1

Ich beginne ein Projekt in Angular 2, und ich habe zum ersten Mal mit Observables zu tun und habe ein paar Zweifel für einen ganz bestimmten Fall.Umgang mit verschachtelten Observablen

Ich habe eine API Service, der so geht:

@Injectable() 
export class UserAPI { 

    [...] 

    login(email: string, password: string): Observable<Response> { 
    let params = new URLSearchParams(); 
    params.set('email', email); 
    params.set('password', password); 

    return this.$http.request(
     new Request({ 
     method: RequestMethod.Post, 
     url: this.baseUrl + '/login', 
     search: params 
     })) 
     .map((response: Response) => response.json()); 
    } 

    [...] 
} 

Sitzung und seine Profildaten Ich bin die Verwaltung der Benutzer (während seiner Sitzung aktiv ist) auf einem User-Dienst, der eine Methode enthält, die diese Anrufe API:

@Injectable() 
export class UserService { 

    [...] 

    constructor(private userAPI: UserAPI, private storage: StorageService) { 
    } 

    login(email: string, password: string) { 
    return this.userAPI.login(email, password).subscribe(
     (res) => { 
     this.storage.store(Constants.storage.session, res.token); 
     }, 
     (err) => { 
     this.storage.destroy(Constants.storage.session); 
     } 
    ); 
    } 

    [...] 
} 

Nun, ich habe auch eine Komponente, die das Login-Formular, und im Erfolgsfall wird behandelt den Benutzer zu einem privaten Bereich der Anwendung umleiten, aber wenn es fehlschlägt, wird das mit einem präsentieren Fehlermeldung (401 oder irgendein anderer Fehler, wenn es zufällig passiert):

@Component({ 
    moduleId: module.id, 
    selector: "auth-login", 
    templateUrl: "auth.login.html" 
}) 
export class LoginComponent { 

    constructor(private router: Router, private userService: UserService) { 
    } 

    [...] 

    login(): void { 
    this.form.loading = true; 
    this.form.error = -100; // arbitrary number 

    this.userService.login(this.form.email, this.form.password); 
     /* 
     .subscribe(
     (res) => { 
     this.router.navigate(["/home", {}]); 
     }, 
     (err) => { 
     this.form.error = err.status; 
     }, 
    () => { 
     this.form.loading = false; 
     } 
    ); 
    */ 
    } 

    [...] 
} 

Bitte beachten Sie den kommentierten Code auf userService.login() Funktionsaufruf. Das sind die Anweisungen, die ich entweder mit dem Erfolg/Fehler des Anrufs machen möchte, aber ich kann es nicht zum Laufen bringen. Ich möchte die Dinge getrennt halten: Der Benutzerdienst verwaltet den Sitzungsteil und die Komponente behandelt die Umleitung oder zeigt dem Benutzer, was schief gelaufen ist.

Was mache ich falsch? Wie geht es hier? Verschachtelte Observablen? Verwenden von Versprechen zwischen der Komponente und dem Benutzerdienst? Ein anderer Ansatz? Ich habe hier auf SO gesucht, konnte aber keinen ähnlichen Fall finden.

Antwort

2

Ich glaube nicht, dass Sie solche Abonnements ketten können; Sie erwarten effektiv thing.subscribe(...).subscribe(...) zu arbeiten. Stattdessen könnten Sie .map und .catch für die Operationen im Dienst nutzen, und lassen Sie die Komponente .subscribe:

login(email: string, password: string) { 
    return this.userAPI.login(email, password) 
     .map(res => { 
     this.storage.store(Constants.storage.session, res.token); 
     return res; 
     }) 
     .catch(err => { 
     this.storage.destroy(Constants.storage.session); 
     return Observable.throw(err); 
     }); 
} 
+0

Das tat es! Vielen Dank für Ihre Hilfe (sowie für die Bearbeitung der Fragen). Immer noch die Seile von Angular 2 und alles, was neu dabei ist. – NunoM

Verwandte Themen