2016-07-25 5 views
0

서비스 HTTP 메서드를 호출하고 결국 오류 메시지를 반환하려고 시도하지만 많은 것을 시도한 후 (약속, 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)을 반환하는 것으로 생각합니다. login 메쏘드는 값이 초기화되지 않는 비동기 요청을하기 때문에 항상 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); 
    } 
} 

이제 로그인 구성 요소에서 비동기 적으로 응답을 수신해야합니다. 이것은 즉시 발생하지 않을 것입니다. (아마 localhost를 사용하면 꽤 빠르지 만 실제 환경에서는 다소 시간이 걸릴 수 있습니다.) 로그인 요청을 기다리는 동안 사용자가 로그인 버튼을 두 번 누르지 못하게하는 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

답변 해 주셔서 감사합니다. 그것은 정확하게 내가 찾고 있었고 매력처럼 일하고 있습니다! Observables 및 의견을 작성해 주셔서 감사 드리며, 정확히 무엇이 문제가되는지 나에게 더욱 분명하게 알려줍니다. '없이해야한다 ';' '관찰 가능한 ''관찰 가능한해야 ' 및 '데이터 => this.handleLogin (데이터) : 동일한 코드를 사용하고자하는 사람들을위한 작은 수정 'data => this.handleLogin (데이터)' – Stijn

관련 문제