http.get
import { HttpClient } from '@angular/common/http';
private fetchPosts() {
this.http
.get('https://PROJECT_NAME.firebaseio.com/posts.json')
.subscribe(posts => {
console.log(posts);
});
}
HttpClient를 이용하여, 매우 간단하게 가져올 수 있습니다.
자료 가공하기
import { map } from 'rxjs/operators';
id라는 key를 추가하여 post를 get하는 코드입니다.
private fetchPosts() {
this.http
.get('https://ng-complete-guide-be717.firebaseio.com/posts.json')
.pipe(
map(responseData => {
const postsArray = [];
for (const key in responseData) {
if (responseData.hasOwnProperty(key)) {
postsArray.push({ ...responseData[key], id: key });
}
}
return postsArray;
})
)
.subscribe(posts => {
// ...
console.log(posts);
});
}
get()와 subscribe()사이에 pipe와 map으로 변경하였습니다.
pipe는 앞에서 사용해 보았듯이,
여러가지 operator로 observable 데이터를 가공(연산)할 수 있도록 합니다.
여기선 map Operator를 사용하였습니다.
한번더 observable로 레핑(wrapping)하는 역할입니다.
id는 랜덤으로 설정되는 글자이기 때문에 string으로 하였습니다.
결과는 캡쳐화면처럼 id의 key:value를 response에 추가해 줍니다.
Type사용하기.
export interface Post {
title: string;
content: string;
id?: string; // optional 물음표 보이시죠? 있을수도 있고 없을 수도 있습니다.
}
먼저 Post를 선언합니다.
private fetchPosts() {
...
.pipe(
map((responseData: {[key: string]: Post}) => {
const postsArray = [];
...
return postsArray;
})
)
...
}
map의 데이터의 타입을 지정해줍니다. key는 string으로 되어있고, value는 Post로 합니다.
이렇게 하여 response데이터의 타입을 알려주게 됩니다.
또한 맵 안에 있는 postsArray도 타입을 지정할 수 있게됩니다.
private fetchPosts() {
...
.pipe(
map((responseData: {[key: string]: Post}) => {
const postsArray: Post[] = [];
...
return postsArray;
})
)
...
}
조금 더 편리한 방법은 response body의 타입을 지정해 주는 방식입니다.
private fetchPosts() {
this.http
.get<{[key: string]: Post}>('https://PROJECT_NAME.firebaseio.com/posts.json')
.pipe(
map(responseData => {
const postsArray: Post[] = [];
for (const key in responseData) {
if (responseData.hasOwnProperty(key)) {
postsArray.push({ ...responseData[key], id: key });
}
}
return postsArray;
})
)
.subscribe(posts => {
// ...
console.log(posts);
});
}
get에 <>를 추가하여 제네릭을 추가합니다.
따로 map과 같은 operator를 사용할 때마다 지정하지 않아도 body와 동일한 타입으로 인식합니다.
Post에도 response body 타입 지정해보기.
onCreatePost(postData: { title: string; content: string }) {
// Send Http request
this.http
.post(
'https://PROJECT_NAME.firebaseio.com/posts.json',
postData
)
.subscribe(responseData => {
console.log(responseData);
});
}
위와 같은 코드가 있을 경우, subscribe의
responseData는 (parameter) responseData: Object로 나타납니다.
하지만 .post<name: string> 을 추가할 경우,
onCreatePost(postData: { title: string; content: string }) {
// Send Http request
this.http
.post<{name: string}>(
'https://PROJECT_NAME.firebaseio.com/posts.json',
postData
)
.subscribe(responseData => {
console.log(responseData);
});
}
responseData는 (parameter) responseData: {name: string;}으로 나타납니다.
Error Handling
http에서 지원하는 error사용.
.subscribe(
(posts: Post[])=> {
this.isFetching = false;
this.loadedPosts = posts;
}, (error) => {
console.log(error);
this.error = error.message;
});
console.log(error)의 내용 입니다.
여러곳에서 에러를 다루어야할 경우, Subject를 생성합니다.
// service.ts
import { Subject} form 'rxjs';
error = new Subject<string>();
.subscribe(
...
},
error => {
this.error.next(error.message);
}
)
다른 곳에서 service.error.subscribe()를 통하여 에러메시지를 핸들링 할 수 있습니다.
catchError를 이용하여, analytics server등을 던질 수 있습니다.
import { throwError } form 'rxjs';
...
,
catchError(errorRes => {
return throwError(errorRes);
});
제네릭 에러를 핸들링하는 작업이 필요할 경우 사용하면 됩니다.
Header Setting
import { HttpHeaders } from '@angular/common/http';
.get<{ [key: string]: Post }>(
'https://ng-complete-guide-be717.firebaseio.com/posts.json',
{
headers: new HttpHeaders({'Custom-Header': 'Hello'})
}
)
hangular/common/http 에서 지원하는 HttpHeaders를 이용하면, 원하는 Header를 추가할 수 있습니다.
해더에 추가한 대로, Custom-Header에 Hello라는 key-value pair로 나오죠?
파라미터 추가하기
import { HttpPramas } from '@angular.common,http';
params: new HttpParams().set('print', 'pretty')
let searchParams = new HttpParams(); // multi. 파라미터 추가하기.
searchParams = searchParams.append('print', 'pretty');
searchParams = searchParams.append('custom', 'key');
javascript로 데이터 받기(data type 변경하기)
2번째 argu.에 observe를 추가합니다.
this.http
.post<{ name: string }>(
'https://ng-complete-guide-c56d3.firebaseio.com/posts.json',
postData,
{observe: 'response'}
)
tap operator
tap 연산자는 Observable을 디버깅 할 수 있도록 정확한 값이나, 다른 사이드 이팩트에 유용합니다.
Note: Observable의 측면에서 subscribe와는 다릅니다. 설령 subscribe하지 않은 Observable이 tap에 의해서 return되어도 , Observer에 의한 사이드 이팩트는 절대 발생하지 않습니다. tap은 단순히 존재하는 실행만 엿볼뿐, subscribe처럼 이벤트를 실행하지 않습니다.
Response body Type 변경하기
deletePosts() {
return this.http.delete(
'https://ng-complete-guide-c56d3.firebaseio.com/posts.json', {
observe: 'events',
responseType: 'json'
}
);
}
interceptors
모든
// auth-intercptor.service.ts
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
export class AuthInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('Resquest in an Its way');
return next.handle(req);
}
}
// app.module.ts
providers: [
{
provide: HTTP_INTERCEPTORS, // 토큰
useClass: AuthInterceptorService,
multi: true
}
],
Header 추가하기
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log(req.url);
const modifiedRequest = req.clone({headers: req.headers.append('Auth', 'xyz')})
console.log('Resquest in an Its way');
return next.handle(modifiedRequest);
}
로깅 인터셉터
// logging-interceptor.service.ts
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEventType } from '@angular/common/http';
import { tap } from 'rxjs/operators';
export class LoggingIntercptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('Outgoing request');
console.log(req.url);
console.log(req.headers);
return next.handle(req).pipe(
tap(event => {
if (event.type === HttpEventType.Response) {
console.log('Incoming response');
console.log(event.body);
}
}));
}
}
// app.module.ts
providers: [
{
provide: HTTP_INTERCEPTORS, // 토큰
useClass: AuthInterceptorService,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: LoggingIntercptorService,
multi: true
}
],
여러개의 인터셉터를 사용할 경우에는 순서가 매우 중요합니다.
providers에서 Logging은 뒤쪽에 위치해야 합니다.
'프로그래밍 > Angular' 카테고리의 다른 글
Dynamic Component (0) | 2019.09.13 |
---|---|
Authentication & Route Protection (0) | 2019.09.06 |
Pipe (0) | 2019.08.15 |
Form - 복습 및 보충 내용 (0) | 2019.08.14 |
FormHandling - Reavice (0) | 2019.07.02 |