Program Tip

http 응답을 처리하는 Angular2

programtip 2020. 11. 8. 10:53
반응형

http 응답을 처리하는 Angular2


서비스 내에서 http 요청의 응답을 구조화하고 처리하는 것에 관한 질문이 있습니다. 저는 Angular2.alpha46 Typescript를 사용 하고 있습니다 (방금 테스트를 시작했습니다-제가 좋아하는 ... 추신 .. 작업하고 github를 통해 기여해 주신 모든 분들께 감사드립니다)

따라서 다음을 수행하십시오.

login-form.component.ts

import {Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2';
import {UserService} from '../../shared/service/user.service';
import {Router} from 'angular2/router';
import {User} from '../../model/user.model';
import {APP_ROUTES, Routes} from '../../core/route.config';

@Component({
    selector: 'login-form',
    templateUrl: 'app/login/components/login-form.component.html',
    directives: [CORE_DIRECTIVES, FORM_DIRECTIVES]
})

export class LoginFormComponent {
    user: User;
    submitted: Boolean = false;

    constructor(private userService:UserService, private router: Router) {
        this.user = new User();
    }

    onLogin() {
        this.submitted = true;

        this.userService.login(this.user,
            () => this.router.navigate([Routes.home.as]))
    }
}

이 구성 요소에서 사용자에게 로그인하기 위해 http 요청을 저장할 userService를 가져옵니다. 서비스는 다음과 같습니다.

user.service.ts

import {Inject} from 'angular2/angular2';
import {Http, HTTP_BINDINGS, Headers} from 'angular2/http';
import {ROUTER_BINDINGS} from 'angular2/router';
import {User} from '../../model/user.model';

export class UserService {

    private headers: Headers;

    constructor(@Inject(Http) private http:Http) {
    }

    login(user: User, done: Function) {
        var postData = "email=" + user.email + "&password=" + user.password;

        this.headers = new Headers();
        this.headers.append('Content-Type', 'application/x-www-form-urlencoded');

        this.http.post('/auth/local', postData, {
                headers: this.headers
            })
            .map((res:any) => res.json())
            .subscribe(
                data => this.saveJwt(data.id_token),
                err => this.logError(err),
                () => done()
            );
    }

    saveJwt(jwt: string) {
        if(jwt) localStorage.setItem('id_token', jwt)
    }

    logError(err: any) {
        console.log(err);
    }
}

내가 원하는 것은 http 요청 후 호출이 반환하는 응답을 처리 할 수있는 것입니다. 예를 들어 사용자 자격 증명이 유효하지 않은 경우 백엔드에서 401 응답을 다시 전달합니다. 내 질문은 응답을 처리하고 결과를 메서드를 호출 한 구성 요소로 다시 반환하는 가장 좋은 방법이 어디인지입니다. 그러면 성공 메시지를 표시하거나 오류 메시지를 표시하도록 뷰를 조작 할 수 있습니다.

현재 로그인 상태의 서비스에서 나는 현재 응답을 처리하지 않고 단순히 원래 구성 요소로 콜백을 수행하고 있지만 이것이 올바른 방법이 아니라고 생각합니까? 누군가가이 전형적인 시나리오에서 무엇을 할 것인지에 대해 밝힐 수 있습니까? 구독 함수의 첫 번째 매개 변수에서 다음과 같이 응답을 처리할까요?

 login(user: User, done: Function) {
     var postData = "email=" + user.email + "&password=" + user.password;

    this.headers = new Headers();
    this.headers.append('Content-Type', 'application/x-www-form-urlencoded');

    this.http.post('/auth/local', postData, {
            headers: this.headers
        })
        .map((res:any) => res.json())
        .subscribe(
            (data) => {
                // Handle response here
                let responseStat = this.handleResponse(data.header)

                // Do some stuff
                this.saveJwt(data.id_token);

                // do call back to original component and pass the response status
                done(responseStat);
            },
            err => this.logError(err)
        );
}

handleResponse(header) {
    if(header.status != 401) {
        return 'success'
    } 

    return 'error blah blah'
}

이 경우 콜백이 괜찮습니까? 아니면 관찰 가능 또는 약속으로 더 잘 처리 할 수 ​​있습니까?

내가 묻는 결론은 ... http 응답의 응답을 처리하고 user.service.ts에서 다시 login-form.component.ts 로의 양식보기에서 상태를 처리하는 가장 좋은 방법은 무엇입니까 ?


알파 47 업데이트

알파 47부터 아래 답변 (alpha46 이하의 경우)이 더 이상 필요하지 않습니다. 이제 Http 모듈이 반환 된 오류를 자동으로 처리합니다. 이제 다음과 같이 쉽습니다.

http
  .get('Some Url')
  .map(res => res.json())
  .subscribe(
    (data) => this.data = data,
    (err) => this.error = err); // Reach here if fails

Alpha 46 이하

당신은의 응답 처리 할 수있는 map(...)전과를 subscribe.

http
  .get('Some Url')
  .map(res => {
    // If request fails, throw an Error that will be caught
    if(res.status < 200 || res.status >= 300) {
      throw new Error('This request has failed ' + res.status);
    } 
    // If everything went fine, return the response
    else {
      return res.json();
    }
  })
  .subscribe(
    (data) => this.data = data, // Reach here if res.status >= 200 && <= 299
    (err) => this.error = err); // Reach here if fails

다음 은 간단한 예제 가있는 plnkr 입니다.

Note that in the next release this won't be necessary because all status codes below 200 and above 299 will throw an error automatically, so you won't have to check them by yourself. Check this commit for more info.


in angular2 2.1.1 I was not able to catch the exception using the (data),(error) pattern, so I implemented it using .catch(...).

It's nice because it can be used with all other Observable chained methods like .retry .map etc.

import {Observable} from 'rxjs/Rx';


  Http
  .put(...)
  .catch(err =>  { 
     notify('UI error handling');
     return Observable.throw(err); // observable needs to be returned or exception raised
  })
  .subscribe(data => ...) // handle success

from documentation:

Returns

(Observable): An observable sequence containing elements from consecutive source sequences until a source sequence terminates successfully.


The service :

import 'rxjs/add/operator/map';

import { Http } from '@angular/http';
import { Observable } from "rxjs/Rx"
import { Injectable } from '@angular/core';

@Injectable()
export class ItemService {
  private api = "your_api_url";

  constructor(private http: Http) {

  }

  toSaveItem(item) {
    return new Promise((resolve, reject) => {
      this.http
        .post(this.api + '/items', { item: item })
        .map(res => res.json())
        // This catch is very powerfull, it can catch all errors
        .catch((err: Response) => {
          // The err.statusText is empty if server down (err.type === 3)
          console.log((err.statusText || "Can't join the server."));
          // Really usefull. The app can't catch this in "(err)" closure
          reject((err.statusText || "Can't join the server."));
          // This return is required to compile but unuseable in your app
          return Observable.throw(err);
        })
        // The (err) => {} param on subscribe can't catch server down error so I keep only the catch
        .subscribe(data => { resolve(data) })
    })
  }
}

In the app :

this.itemService.toSaveItem(item).then(
  (res) => { console.log('success', res) },
  (err) => { console.log('error', err) }
)

참고URL : https://stackoverflow.com/questions/33941836/angular2-handling-http-response

반응형