2016-07-25 39 views
0

我试图调用一个服务HTTP方法,并最终返回一个错误消息,但尝试了很多事情(Promises,Observables,...)一周后,我可以'让它工作。我希望有人能帮助我?Angular2从组件中的服务调用登录函数并返回错误

我对Angular2很陌生,一个人在这个项目上工作,没有任何人在我身边任何角度的专业知识。我确实参加了为期3天的培训课程。

组件

@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'); 
    } 
} 

回答

1

我觉得你的问题是,你的登录方法返回一个平坦值(errorMessage)。由于登录方法正在进行异步请求,该值不会被初始化,它将始终返回null。如果我要设置这个,我会让登录方法返回Observable

然后,为了使事情更复杂一点,你似乎想在登录后进行连续调用以获取登录用户。如果你不希望你的登录方法发出,直到你完成了两个调用,你必须以某种方式将它们结合起来。我认为switch可以做到这一点。

@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); 
    } 
} 

现在在您的登录组件中,您将需要异步侦听响应。这不会立即发生(可能本地主机很快,但在现实世界中可能需要一段时间),所以我添加了一个loginDisabled,您可以使用它来防止用户在等待登录请求时两次登录登录按钮被履行。

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

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

    private login(credentials) { 
    // Method calling the login service 
    // Could return an error, or nothing 
    this.loginDisabled = true; 
    this.auth.login(credentials).subscribe(
     rsp => { 
     //On success, navigate to overview page 
     this.navController.setRoot(OverviewPage); 
     }, err => { 
     //On failure, display error message 
     this.error = err; 
     this.loginDisabled = false; 
    }); 

    } 
} 

没有承诺这是全部正确的(我没有任何可以测试它),但它应该是正确的大方向。

+0

非常感谢您的回答!这正是我寻找和工作的魅力! 非常感谢你制定观察结果和评论,这让我更清楚地知道究竟是什么东西。 小补丁谁想要使用相同的代码的人: '可观察'应该是'可观察' 和 '数据=> this.handleLogin(数据);'应该没有“;” 'data => this.handleLogin(data)' – Stijn

相关问题