SlideShare a Scribd company logo
Http Client
Routing & Navigation
- 권동준 -
Http
1. Http 요청은 기본적으로 XMLHttpRequest를 기반으로 사용한다.
2. Http는 injectable 클래스로 Http 요청 시 사용.
3. Promise과 Observable(Rxjs)으로 사용할 수 있지만 Angular2.0에서는
기본적으로 Http요청 후 응답이 왔을 시 Observable를 리턴.
4.Promise를 사용할 경우 angular2 http에서는 Observable반환 하기 때문에 새로운
promise로 선언 후 반환해야 된다.(자세한 설명은 예제를 보며..)
5. Rx.js를 알면 편하고 나아가서 반응형 프로그래밍을 이해하면 더욱 좋음.
Http
Http를 사용하려면 HTTP_PROVIDERS 의존성 주입(DI)
(Http는 injectable 클래스)
Html에도 선언
providers: [
/* HTTP_PROVIDERS 의존성 주입 */
HTTP_PROVIDERS,
/* HeroService 의존성 주입 */
HeroService,
// in-memory web api providers
provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server
provide(SEED_DATA, { useClass: HeroData }) // in-mem server data
]
<script src="node_modules/angular2/bundles/http.dev.js"></script>
Http @Injectable()
export class HeroService {
constructor (private http: Http){}
private _heroesUrl = 'app/heroes';
getHeroes (): Observable<Hero[]> {
return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError);
}
private extractData(res: Response): Hero[] {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body: any = res.json();
return body.data || [];
}
private handleError (error: any) {
let errMsg = error.message || 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
꼭 response 개체를 잘 사용하기 위해서는
2가지를 해야한다.
1. check for a bad response
2. parse the response data into a JSON
object
response 개체 자체를 리턴하는 것은 안좋다!
server의 정보를 숨기고 필요한 정보만을
return하는 것이 좋으며 사용자 입장에서도 그
데이터만 필요로 하기 때문이다. 어디서
무엇을 하는지는 굳이 알 필요가 없다.
getHeroes() {
this._heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes, error => this.errorMessage =
<any>error);
}
Http
addHero (name: string) {
if (!name) {return;}
this._heroService.addHero(name)
.subscribe(
hero => this.heroes.push(hero),
error => this.errorMessage = <any>error);
}
@Injectable()
export class HeroService {
constructor (private http: Http){}
private _heroesUrl = 'app/heroes';
addHero (name: string): Observable<Hero> {
let body = JSON.stringify({ name });
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this._heroesUrl, body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response): Hero[] {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body: any = res.json();
return body.data || [];
}
private handleError (error: any) {
let errMsg = error.message || 'Server error';
console.log('Error Start');
console.error(errMsg);
return Observable.throw(errMsg);
}
}
Header 정보 등등은
BaseRequestOptions 사용하면 미리 지정 가능
Http
catch는 try-catch의 catch라고
생각하면 이해가 빠르다.
map안에서 throw new Error을
하면 catch에서 선언된
handleError을 실행한다.
@Injectable()
export class HeroService {
constructor (private http: Http){}
private _heroesUrl = 'app/heroes';
getHeroes (): Observable<Hero[]> {
return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError);
}
private extractData(res: Response): Hero[] {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body: any = res.json();
return body.data || [];
}
private handleError (error: any) {
let errMsg = error.message || 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
Http
1. get(url: string, options?: RequestOptionsArgs) : Observable<Response>
2. post(url: string, body: string, options?: RequestOptionsArgs) : Observable<Response>
3. put(url: string, body: string, options?: RequestOptionsArgs) : Observable<Response>
4. delete(url: string, options?: RequestOptionsArgs) : Observable<Response>
Jsonp
1. JSONP는 HTTP서비스의 확장이며, GET요청에 제한을 둔다.
2. JSONP는 읽기 전용이다.
3. JSONP_PROVIDERS로 의존성 주입을 한다.
4. JSONP역시 injectable 클래스
5. Promise과 Observable(Rxjs)으로 사용할 수 있지만 Angular2.0에서는
기본적으로 Http요청 후 응답이 왔을 시 Observable를 리턴.
Jsonp
1. Jsonp를 사용하려면 JSONP_PROVIDERS 의존성 주입(DI)
(JSONP는 injectable 클래스)
@Component({
selector: 'my-wiki',
providers:[JSONP_PROVIDERS, WikipediaService]
})
Jsonp
@Injectable()
export class WikipediaService {
constructor(private jsonp: Jsonp) {}
search (term: string) {
let wikiUrl = 'http://en.wikipedia.org/w/api.php';
var params = new URLSearchParams();
params.set('search', term); // the user's search value
params.set('action', 'opensearch');
params.set('format', 'json');
params.set('callback', 'JSONP_CALLBACK');
return this.jsonp
.get(wikiUrl, { search: params })
.map(request => <string[]> request.json()[1]);
}
}
@Component({
selector: 'my-wiki',
template: `
<h1>Wikipedia Demo</h1>
<p><i>Fetches after each keystroke</i></p>
<input #term (keyup)="search(term.value)"/>
<ul>
<li *ngFor="#item of items | async">{{item}}</li>
</ul>
`,
providers:[JSONP_PROVIDERS, WikipediaService]
})
export class WikiComponent {
constructor (private _wikipediaService: WikipediaService) {}
items: Observable<string[]>;
search (term: string) {
this.items = this._wikipediaService.search(term);
}
}
Promise & Observable
Angular2.0 Http는 Observable 개체를 return한다. 하지만 Promise도 사용할 수
있게 제공한다.
/* Observable */
return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError);
/* Promise */
return this.http.get(this._heroesUrl) .toPromise().then(this.extractData).catch(this.handleError);
/* Observable */
this._heroService.getHeroes().subscribe(heroes => this.heroes = heroes, error => this.errorMessage = <any>error);
/* Promise */
this._heroService.getHeroes().then(heroes => this.heroes = heroes, error => this.errorMessage = <any>error);
Promise or Observable
const Rx = require('rx');
const promise = new Promise((resolve) => {
setTimeout(() => {
console.log('1 - 이것도 실행?');
resolve(100)
}, 500);
console.log('promise 시작');
});
// promise.then(x => console.log(x));
const observable = Rx.Observable.create((observer) => {
setTimeout(() => {
console.log('2 - 이것도 실행?');
observer.onNext(100);
}, 500);
console.log('observable 시작');
});
// observable.forEach(x => console.log(x));
차이점 보기!
Routing & Navigation
1. Routing의 URL은 기본적으로 HTML5 pushState 스타일이다.
2. 자식과 부모 라우터를 구성할 수 있다.
3. Router Life Cycle Hooks가 존재한다.(3가지!)
4. 자식과 부모 사이의 query parameter은 matrix URL방식이다.
Routing & Navigation
Html 추가 및 ROUTER_PROVIDERS 의존성 주입(DI)
import {ROUTER_PROVIDERS} from "angular2/router";
import {AppComponent} from "./component/app.component";
import {bootstrap} from "angular2/platform/browser";
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<base href="/">
HTML5 pushState Style
Routing & Navigation
/**
* 라우터 설정
*/
@RouteConfig([
{
/* 자식과 부모와의 관계이므로 기본 path 이후는 ...으로 표시 */
path: '/crisis-center/...',
/* 중복이 되면 안되며, PascalCase 방식으로 네이밍을 해야된다. */
name: 'CrisisCenter',
component: CrisisCenterComponent,
/*
해당 url에 어떠한 정보가 없으면 아래의 useAsDefault로 선언된 라우터로 이동된다.
(localhost/ 들어오면 정보가 없기 때문에 아래의 정보가 있는 곳으로 이동)
*/
useAsDefault: true
},
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
/* 할당된 url이 없을시 아래와 같이 지정한다. 물론 404 Component를 만들어서 넣어도 된다. */
{ path: '/**', redirectTo: ['CrisisCenter'] }
])
Routing & Navigation
@Component({
selector: 'my-app',
template: `
<h1 class="title">Component Router</h1>
<nav>
<a [routerLink]="['CrisisCenter']">Crisis Center</a>
<!-- 부모의 라우터에서 자식의 라우터중 어디로 갈지 배열로 선언해준다. -->
<a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center-list</a>
<a [routerLink]="['Heroes']">Heroes</a>
<!-- parmater 값은 name 배열 다음에 json형식으로 넣어준다. -->
<a [routerLink]="['HeroDetail', {id: 11}]">11. Hero Detail</a>
</nav>
<!-- 라우터에 따라 라우팅 되는 곳 -->
<router-outlet></router-outlet>
`,
providers: [DialogService, HeroService],
/* 이게 선언이 되여 RouterOutlet, RouterLink을 사용할 수 있다. */
directives: [ROUTER_DIRECTIVES]
})
Routing & Navigation
Routing 방식
1. URL 변경 방식
1) URL이 변경이 되면 Router의 Path를 찾아 매칭.
2) component instance를 생성해주거나 검색.
3) view에 표시해준다.
2. 이름 방식으로 route 호출
1) 해당 이름의 path로 경로를 구성하고 주소위치랑 히스토리를 업데이트.
2) component instance를 생성해주거나 검색.
3) view에 표시해준다.
Routing & Navigation
// AppComponent (부모)
@RouteConfig([
{
/* 자식과 부모와의 관계이므로 기본 path 이후는 …으로 표시 */
path: '/crisis-center/…',
name: 'CrisisCenter',
component: CrisisCenterComponent,
useAsDefault: true
}
])
부모 Component의 Template에 아래와 같이
선언되어야한다.
<router-outlet></router-outlet>
자식 CrisisCenterComponent의 Template에 아래와 같이
선언되어야한다.
<router-outlet></router-outlet>
// CrisisCenterComponent (자식)
@RouteConfig([
{
path:'/',
name: 'CrisisList',
component: CrisisListComponent,
useAsDefault: true
},
{
path:'/:id',
name: 'CrisisDetail',
component: CrisisDetailComponent
}
])
자식과 부모 사이의 query parameter은 matrix URL방식이다.
localhost/crisi-center/;id=1;foo=foo
Routing & Navigation
export class HeroListComponent implements OnInit {
heroes: Hero[];
private _selectedId: number;
constructor(
private _service: HeroService,
private _router: Router,
routeParams: RouteParams) {
/* routeParams를 이용하여 parameter값을 가지고 올수 있다. url/query param 전부 가지고 온다. */
this._selectedId = +routeParams.get('id');
}
isSelected(hero: Hero) { return hero.id === this._selectedId; }
onSelect(hero: Hero) {
this._router.navigate( ['HeroDetail', { id: hero.id }] );
}
ngOnInit() {
this._service.getHeroes().then(heroes => this.heroes = heroes)
}
}
Routing & Navigation
constructor(
routeParams: RouteParams) {
this._selectedId = +routeParams.get('id');
}
ngOnInit() {
this._selectedId =+ _routeParams.get('id');
}
VS
2가지의 차이점은 결국 시점 차이다.
ngOnInit은 구성요소가 초기화 될때 호출되고, constructor는 구성요소가 구성될때 실행된다.
결론적으로 constructor먼저 실행되고 ngOnInit이 호출된다. Angular에서는 테스트때문에
constructor보다는 ngOnInit방식(자스민에서 테스트가 가능하다)으로 하는걸 추천한다. 하지만 굳이
테스트가 필요하지 않은 것 혹은 해당 시점에 맞게 프로그래밍 할 때는 다른 방식을 해도 된다.
Routing & Navigation
Router Life Cycle Hooks
1. CanActivate
2. OnActivate
3. CanDeactivate
이 3가지의 Hooks는 각각의 시점이 서로 다르고 사용용도도 다르다.
Routing & Navigation
@CanActivate((next, prev) => {
/* next는 이동하려는 Route, prev는 현재 라우터 */
console.log(`next = ${next.urlPath} // now = ${prev ? prev.urlPath : null}`);
/* false이면 routing이 취소된다. Promise를 통해서 true 혹은 false를 줄수 있다. */
return new Promise(resolve => {
setTimeout(() => resolve(true), 10000);
});
})
@CanActivate
1. 시점 : Routing이 되기 직전.(angular1의 resolve)
2. 용도 : Login/Auth 체크시 많이 사용된다.
3. return : true이면 Routing이 되며, false이면 Routing이 취소된다.
Routing & Navigation
routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
this.log = `Finished navigating from "${prev ? prev.urlPath : 'null'}" to "${next.urlPath}"`;
console.log(this.log);
/* Routing이 완료되어 구성되자마자 실행이 된다. */
return new Promise(resolve => {
setTimeout(() => resolve(null), 1000);
});
}
onActivate
1. 시점 : Routing 완료되어 구성되자마자 실행
2. return : promise를 통해서 리턴이되며 해당 promise가 될때까지
기다린다.
Routing & Navigation
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
return this._dialog.confirm('Discard changes?');
}
onActivate
1. 시점 : 해당 Route에서 다른 Route로 이동할 때 된다.(이동하기 바로전)
2. return : true이면 이동이되며, false면 이동이 안된다.
Routing & Navigation
@CanActivate((next, prev) => {
console.log(`CanActivate`);
return true
})
export class CrisisDetailComponent implements OnInit, CanDeactivate {
constructor() { console.log(`constructor`); }
ngOnInit() {
console.log(`ngOnInit`);
}
routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
console.log(`OnActivate`);
/* Routing이 완료되어 구성되자마자 실행이 된다. */
return new Promise(resolve => {
setTimeout(() => resolve(null), 1000);
});
}
routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any {
if (!this.crisis || this.crisis.name === this.editName) {
return true;
}
return this._dialog.confirm('Discard changes?');
}
}
출력 되는 순서
1. CanActivate
2. constructor
3. OnActivate
4. ngOnInit
Routing & Navigation
해당 라우터로 이동시에
<a [routerLink]="['CrisisCenter']">
위와 같이 선언이 되어 있는 부분에 해당 라우터를 호출을 하면
아래와 같이 자동으로 class를 부여한다.
<a href="/crisis-center" class="router-link-active">
Routing & Navigation
상세
아래와 같이 부모 자식간의 관계가 아닌 같은 노드의 다른 라우터이기
때문에 heroes의 상세에 들어가도 Heroes에 class가 부여되지 않는다.
서로 다른 라우터로 인식하기 때문이다.
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
Routing & Navigation
상세
아래와 같이 부모와 자식관계이기 때문에 class가 부여된다.
부모
{
path: '/crisis-center/...',
name: 'CrisisCenter',
component: CrisisCenterComponent,
useAsDefault: true
}
자식
{path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true},
{path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
예제 소스
Http
- https://github.com/mayajuni/angular2-http
Routing & Nav
- https://github.com/mayajuni/angular2-routing-nav

More Related Content

What's hot (20)

PDF
진짜기초 Node.js
Woo Jin Kim
 
PDF
ReactJS | 서버와 클라이어트에서 동시에 사용하는
Taegon Kim
 
PPTX
Angular2를 위한 타입스크립트
Jin wook
 
PDF
[11]Android DataBinding : 기초에서 고급까지
NAVER Engineering
 
PDF
Protocol Oriented Programming in Swift
SeongGyu Jo
 
PPTX
Web Components 101 polymer & brick
yongwoo Jeon
 
PDF
Html5 web workers
Woo Jin Kim
 
PPTX
Startup JavaScript 8 - NPM, Express.JS
Circulus
 
PDF
Express 프레임워크
Choonghyun Yang
 
PPTX
AngularJS의 개발방식에 대하여
Jin wook
 
PDF
처음배우는 자바스크립트, 제이쿼리 #1
성일 한
 
PDF
자바스크립트 프레임워크 살펴보기
Jeado Ko
 
PPTX
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
정석 양
 
PDF
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Hyuncheol Jeon
 
PDF
Node.js intro
Chul Ju Hong
 
PDF
Javascript 조금 더 잘 알기
jongho jeong
 
PPTX
Web workers
Hyun Jun Jang
 
PPTX
Dependency Injection 소개
beom kyun choi
 
PPTX
파이썬 언어 기초
beom kyun choi
 
진짜기초 Node.js
Woo Jin Kim
 
ReactJS | 서버와 클라이어트에서 동시에 사용하는
Taegon Kim
 
Angular2를 위한 타입스크립트
Jin wook
 
[11]Android DataBinding : 기초에서 고급까지
NAVER Engineering
 
Protocol Oriented Programming in Swift
SeongGyu Jo
 
Web Components 101 polymer & brick
yongwoo Jeon
 
Html5 web workers
Woo Jin Kim
 
Startup JavaScript 8 - NPM, Express.JS
Circulus
 
Express 프레임워크
Choonghyun Yang
 
AngularJS의 개발방식에 대하여
Jin wook
 
처음배우는 자바스크립트, 제이쿼리 #1
성일 한
 
자바스크립트 프레임워크 살펴보기
Jeado Ko
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
정석 양
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Hyuncheol Jeon
 
Node.js intro
Chul Ju Hong
 
Javascript 조금 더 잘 알기
jongho jeong
 
Web workers
Hyun Jun Jang
 
Dependency Injection 소개
beom kyun choi
 
파이썬 언어 기초
beom kyun choi
 

Viewers also liked (20)

PPTX
RxJS and Reactive Programming - Modern Web UI - May 2015
Ben Lesh
 
PPTX
Angular2 inter3
Oswald Campesato
 
PDF
Authentication and Authorization Architecture in the MEAN Stack
FITC
 
PDF
Modules in angular 2.0 beta.1
David Rodenas
 
PDF
Adventures with Angular 2
Dragos Ionita
 
PDF
How Angular2 Can Improve Your AngularJS Apps Today!
Nir Kaufman
 
PDF
Angular2 - getting-ready
Nir Kaufman
 
PPTX
Angular2를 활용한 컴포넌트 중심의 개발
Jin wook
 
PDF
Angular2 workshop
Nir Kaufman
 
PPTX
Angular 2 어디까지 왔을까
장현 한
 
PDF
Cascadia.js: Don't Cross the Streams
mattpodwysocki
 
PDF
Angular 2 - Core Concepts
Fabio Biondi
 
PDF
Functional Reactive Programming With RxSwift
선협 이
 
ODP
Introduction to Angular 2
Knoldus Inc.
 
PPTX
Functional Reactive Programming with RxJS
stefanmayer13
 
PDF
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
NAVER / MusicPlatform
 
PDF
Reactive, component 그리고 angular2
Jeado Ko
 
PDF
Getting Started with Angular 2
FITC
 
PPTX
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
Jong Wook Kim
 
RxJS and Reactive Programming - Modern Web UI - May 2015
Ben Lesh
 
Angular2 inter3
Oswald Campesato
 
Authentication and Authorization Architecture in the MEAN Stack
FITC
 
Modules in angular 2.0 beta.1
David Rodenas
 
Adventures with Angular 2
Dragos Ionita
 
How Angular2 Can Improve Your AngularJS Apps Today!
Nir Kaufman
 
Angular2 - getting-ready
Nir Kaufman
 
Angular2를 활용한 컴포넌트 중심의 개발
Jin wook
 
Angular2 workshop
Nir Kaufman
 
Angular 2 어디까지 왔을까
장현 한
 
Cascadia.js: Don't Cross the Streams
mattpodwysocki
 
Angular 2 - Core Concepts
Fabio Biondi
 
Functional Reactive Programming With RxSwift
선협 이
 
Introduction to Angular 2
Knoldus Inc.
 
Functional Reactive Programming with RxJS
stefanmayer13
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
NAVER / MusicPlatform
 
Reactive, component 그리고 angular2
Jeado Ko
 
Getting Started with Angular 2
FITC
 
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
Jong Wook Kim
 
Ad

Similar to Angular2 router&http (20)

PPTX
Nodejs express
Hyosung Jeon
 
KEY
vine webdev
dcfc1997
 
PPTX
[스프링 스터디 2일차] 서비스 추상화
AnselmKim
 
PDF
overview of spring4
Arawn Park
 
PPTX
Xe hack
sejin7940
 
PPTX
Node.js and react
HyungKuIm
 
PDF
막하는스터디 두번째만남 Express(20151025)
연웅 조
 
PDF
파이썬 웹프로그래밍 1탄
SeongHyun Ahn
 
PDF
JSP 프로그래밍 #03 서블릿
Myungjin Lee
 
PPTX
Ksug 세미나 (윤성준) (20121208)
Sungjoon Yoon
 
PPTX
One-day-codelab
WebFrameworks
 
PDF
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
PPTX
Nest js 101
Daniel Lim
 
PPTX
[스프링 스터디 3일차] @MVC
AnselmKim
 
PPTX
4-3. jquery
JinKyoungHeo
 
PDF
자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)
DK Lee
 
PPTX
4-2. ajax
JinKyoungHeo
 
PDF
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
LanarkSeung
 
PPTX
자바스크립트 클래스의 프로토타입(prototype of class)
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
PPT
Multithread programming 20151206_서진택
JinTaek Seo
 
Nodejs express
Hyosung Jeon
 
vine webdev
dcfc1997
 
[스프링 스터디 2일차] 서비스 추상화
AnselmKim
 
overview of spring4
Arawn Park
 
Xe hack
sejin7940
 
Node.js and react
HyungKuIm
 
막하는스터디 두번째만남 Express(20151025)
연웅 조
 
파이썬 웹프로그래밍 1탄
SeongHyun Ahn
 
JSP 프로그래밍 #03 서블릿
Myungjin Lee
 
Ksug 세미나 (윤성준) (20121208)
Sungjoon Yoon
 
One-day-codelab
WebFrameworks
 
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Nest js 101
Daniel Lim
 
[스프링 스터디 3일차] @MVC
AnselmKim
 
4-3. jquery
JinKyoungHeo
 
자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)
DK Lee
 
4-2. ajax
JinKyoungHeo
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
LanarkSeung
 
자바스크립트 클래스의 프로토타입(prototype of class)
탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Multithread programming 20151206_서진택
JinTaek Seo
 
Ad

Angular2 router&http

  • 1. Http Client Routing & Navigation - 권동준 -
  • 2. Http 1. Http 요청은 기본적으로 XMLHttpRequest를 기반으로 사용한다. 2. Http는 injectable 클래스로 Http 요청 시 사용. 3. Promise과 Observable(Rxjs)으로 사용할 수 있지만 Angular2.0에서는 기본적으로 Http요청 후 응답이 왔을 시 Observable를 리턴. 4.Promise를 사용할 경우 angular2 http에서는 Observable반환 하기 때문에 새로운 promise로 선언 후 반환해야 된다.(자세한 설명은 예제를 보며..) 5. Rx.js를 알면 편하고 나아가서 반응형 프로그래밍을 이해하면 더욱 좋음.
  • 3. Http Http를 사용하려면 HTTP_PROVIDERS 의존성 주입(DI) (Http는 injectable 클래스) Html에도 선언 providers: [ /* HTTP_PROVIDERS 의존성 주입 */ HTTP_PROVIDERS, /* HeroService 의존성 주입 */ HeroService, // in-memory web api providers provide(XHRBackend, { useClass: InMemoryBackendService }), // in-mem server provide(SEED_DATA, { useClass: HeroData }) // in-mem server data ] <script src="node_modules/angular2/bundles/http.dev.js"></script>
  • 4. Http @Injectable() export class HeroService { constructor (private http: Http){} private _heroesUrl = 'app/heroes'; getHeroes (): Observable<Hero[]> { return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError); } private extractData(res: Response): Hero[] { if (res.status < 200 || res.status >= 300) { throw new Error('Bad response status: ' + res.status); } let body: any = res.json(); return body.data || []; } private handleError (error: any) { let errMsg = error.message || 'Server error'; console.error(errMsg); return Observable.throw(errMsg); } } 꼭 response 개체를 잘 사용하기 위해서는 2가지를 해야한다. 1. check for a bad response 2. parse the response data into a JSON object response 개체 자체를 리턴하는 것은 안좋다! server의 정보를 숨기고 필요한 정보만을 return하는 것이 좋으며 사용자 입장에서도 그 데이터만 필요로 하기 때문이다. 어디서 무엇을 하는지는 굳이 알 필요가 없다. getHeroes() { this._heroService.getHeroes() .subscribe(heroes => this.heroes = heroes, error => this.errorMessage = <any>error); }
  • 5. Http addHero (name: string) { if (!name) {return;} this._heroService.addHero(name) .subscribe( hero => this.heroes.push(hero), error => this.errorMessage = <any>error); } @Injectable() export class HeroService { constructor (private http: Http){} private _heroesUrl = 'app/heroes'; addHero (name: string): Observable<Hero> { let body = JSON.stringify({ name }); let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this.http.post(this._heroesUrl, body, options) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response): Hero[] { if (res.status < 200 || res.status >= 300) { throw new Error('Bad response status: ' + res.status); } let body: any = res.json(); return body.data || []; } private handleError (error: any) { let errMsg = error.message || 'Server error'; console.log('Error Start'); console.error(errMsg); return Observable.throw(errMsg); } } Header 정보 등등은 BaseRequestOptions 사용하면 미리 지정 가능
  • 6. Http catch는 try-catch의 catch라고 생각하면 이해가 빠르다. map안에서 throw new Error을 하면 catch에서 선언된 handleError을 실행한다. @Injectable() export class HeroService { constructor (private http: Http){} private _heroesUrl = 'app/heroes'; getHeroes (): Observable<Hero[]> { return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError); } private extractData(res: Response): Hero[] { if (res.status < 200 || res.status >= 300) { throw new Error('Bad response status: ' + res.status); } let body: any = res.json(); return body.data || []; } private handleError (error: any) { let errMsg = error.message || 'Server error'; console.error(errMsg); return Observable.throw(errMsg); } }
  • 7. Http 1. get(url: string, options?: RequestOptionsArgs) : Observable<Response> 2. post(url: string, body: string, options?: RequestOptionsArgs) : Observable<Response> 3. put(url: string, body: string, options?: RequestOptionsArgs) : Observable<Response> 4. delete(url: string, options?: RequestOptionsArgs) : Observable<Response>
  • 8. Jsonp 1. JSONP는 HTTP서비스의 확장이며, GET요청에 제한을 둔다. 2. JSONP는 읽기 전용이다. 3. JSONP_PROVIDERS로 의존성 주입을 한다. 4. JSONP역시 injectable 클래스 5. Promise과 Observable(Rxjs)으로 사용할 수 있지만 Angular2.0에서는 기본적으로 Http요청 후 응답이 왔을 시 Observable를 리턴.
  • 9. Jsonp 1. Jsonp를 사용하려면 JSONP_PROVIDERS 의존성 주입(DI) (JSONP는 injectable 클래스) @Component({ selector: 'my-wiki', providers:[JSONP_PROVIDERS, WikipediaService] })
  • 10. Jsonp @Injectable() export class WikipediaService { constructor(private jsonp: Jsonp) {} search (term: string) { let wikiUrl = 'http://en.wikipedia.org/w/api.php'; var params = new URLSearchParams(); params.set('search', term); // the user's search value params.set('action', 'opensearch'); params.set('format', 'json'); params.set('callback', 'JSONP_CALLBACK'); return this.jsonp .get(wikiUrl, { search: params }) .map(request => <string[]> request.json()[1]); } } @Component({ selector: 'my-wiki', template: ` <h1>Wikipedia Demo</h1> <p><i>Fetches after each keystroke</i></p> <input #term (keyup)="search(term.value)"/> <ul> <li *ngFor="#item of items | async">{{item}}</li> </ul> `, providers:[JSONP_PROVIDERS, WikipediaService] }) export class WikiComponent { constructor (private _wikipediaService: WikipediaService) {} items: Observable<string[]>; search (term: string) { this.items = this._wikipediaService.search(term); } }
  • 11. Promise & Observable Angular2.0 Http는 Observable 개체를 return한다. 하지만 Promise도 사용할 수 있게 제공한다. /* Observable */ return this.http.get(this._heroesUrl).map(this.extractData).catch(this.handleError); /* Promise */ return this.http.get(this._heroesUrl) .toPromise().then(this.extractData).catch(this.handleError); /* Observable */ this._heroService.getHeroes().subscribe(heroes => this.heroes = heroes, error => this.errorMessage = <any>error); /* Promise */ this._heroService.getHeroes().then(heroes => this.heroes = heroes, error => this.errorMessage = <any>error);
  • 12. Promise or Observable const Rx = require('rx'); const promise = new Promise((resolve) => { setTimeout(() => { console.log('1 - 이것도 실행?'); resolve(100) }, 500); console.log('promise 시작'); }); // promise.then(x => console.log(x)); const observable = Rx.Observable.create((observer) => { setTimeout(() => { console.log('2 - 이것도 실행?'); observer.onNext(100); }, 500); console.log('observable 시작'); }); // observable.forEach(x => console.log(x)); 차이점 보기!
  • 13. Routing & Navigation 1. Routing의 URL은 기본적으로 HTML5 pushState 스타일이다. 2. 자식과 부모 라우터를 구성할 수 있다. 3. Router Life Cycle Hooks가 존재한다.(3가지!) 4. 자식과 부모 사이의 query parameter은 matrix URL방식이다.
  • 14. Routing & Navigation Html 추가 및 ROUTER_PROVIDERS 의존성 주입(DI) import {ROUTER_PROVIDERS} from "angular2/router"; import {AppComponent} from "./component/app.component"; import {bootstrap} from "angular2/platform/browser"; bootstrap(AppComponent, [ROUTER_PROVIDERS]); <script src="node_modules/angular2/bundles/router.dev.js"></script> <base href="/"> HTML5 pushState Style
  • 15. Routing & Navigation /** * 라우터 설정 */ @RouteConfig([ { /* 자식과 부모와의 관계이므로 기본 path 이후는 ...으로 표시 */ path: '/crisis-center/...', /* 중복이 되면 안되며, PascalCase 방식으로 네이밍을 해야된다. */ name: 'CrisisCenter', component: CrisisCenterComponent, /* 해당 url에 어떠한 정보가 없으면 아래의 useAsDefault로 선언된 라우터로 이동된다. (localhost/ 들어오면 정보가 없기 때문에 아래의 정보가 있는 곳으로 이동) */ useAsDefault: true }, {path: '/heroes', name: 'Heroes', component: HeroListComponent}, {path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent}, /* 할당된 url이 없을시 아래와 같이 지정한다. 물론 404 Component를 만들어서 넣어도 된다. */ { path: '/**', redirectTo: ['CrisisCenter'] } ])
  • 16. Routing & Navigation @Component({ selector: 'my-app', template: ` <h1 class="title">Component Router</h1> <nav> <a [routerLink]="['CrisisCenter']">Crisis Center</a> <!-- 부모의 라우터에서 자식의 라우터중 어디로 갈지 배열로 선언해준다. --> <a [routerLink]="['CrisisCenter', 'CrisisList']">Crisis Center-list</a> <a [routerLink]="['Heroes']">Heroes</a> <!-- parmater 값은 name 배열 다음에 json형식으로 넣어준다. --> <a [routerLink]="['HeroDetail', {id: 11}]">11. Hero Detail</a> </nav> <!-- 라우터에 따라 라우팅 되는 곳 --> <router-outlet></router-outlet> `, providers: [DialogService, HeroService], /* 이게 선언이 되여 RouterOutlet, RouterLink을 사용할 수 있다. */ directives: [ROUTER_DIRECTIVES] })
  • 17. Routing & Navigation Routing 방식 1. URL 변경 방식 1) URL이 변경이 되면 Router의 Path를 찾아 매칭. 2) component instance를 생성해주거나 검색. 3) view에 표시해준다. 2. 이름 방식으로 route 호출 1) 해당 이름의 path로 경로를 구성하고 주소위치랑 히스토리를 업데이트. 2) component instance를 생성해주거나 검색. 3) view에 표시해준다.
  • 18. Routing & Navigation // AppComponent (부모) @RouteConfig([ { /* 자식과 부모와의 관계이므로 기본 path 이후는 …으로 표시 */ path: '/crisis-center/…', name: 'CrisisCenter', component: CrisisCenterComponent, useAsDefault: true } ]) 부모 Component의 Template에 아래와 같이 선언되어야한다. <router-outlet></router-outlet> 자식 CrisisCenterComponent의 Template에 아래와 같이 선언되어야한다. <router-outlet></router-outlet> // CrisisCenterComponent (자식) @RouteConfig([ { path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true }, { path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent } ]) 자식과 부모 사이의 query parameter은 matrix URL방식이다. localhost/crisi-center/;id=1;foo=foo
  • 19. Routing & Navigation export class HeroListComponent implements OnInit { heroes: Hero[]; private _selectedId: number; constructor( private _service: HeroService, private _router: Router, routeParams: RouteParams) { /* routeParams를 이용하여 parameter값을 가지고 올수 있다. url/query param 전부 가지고 온다. */ this._selectedId = +routeParams.get('id'); } isSelected(hero: Hero) { return hero.id === this._selectedId; } onSelect(hero: Hero) { this._router.navigate( ['HeroDetail', { id: hero.id }] ); } ngOnInit() { this._service.getHeroes().then(heroes => this.heroes = heroes) } }
  • 20. Routing & Navigation constructor( routeParams: RouteParams) { this._selectedId = +routeParams.get('id'); } ngOnInit() { this._selectedId =+ _routeParams.get('id'); } VS 2가지의 차이점은 결국 시점 차이다. ngOnInit은 구성요소가 초기화 될때 호출되고, constructor는 구성요소가 구성될때 실행된다. 결론적으로 constructor먼저 실행되고 ngOnInit이 호출된다. Angular에서는 테스트때문에 constructor보다는 ngOnInit방식(자스민에서 테스트가 가능하다)으로 하는걸 추천한다. 하지만 굳이 테스트가 필요하지 않은 것 혹은 해당 시점에 맞게 프로그래밍 할 때는 다른 방식을 해도 된다.
  • 21. Routing & Navigation Router Life Cycle Hooks 1. CanActivate 2. OnActivate 3. CanDeactivate 이 3가지의 Hooks는 각각의 시점이 서로 다르고 사용용도도 다르다.
  • 22. Routing & Navigation @CanActivate((next, prev) => { /* next는 이동하려는 Route, prev는 현재 라우터 */ console.log(`next = ${next.urlPath} // now = ${prev ? prev.urlPath : null}`); /* false이면 routing이 취소된다. Promise를 통해서 true 혹은 false를 줄수 있다. */ return new Promise(resolve => { setTimeout(() => resolve(true), 10000); }); }) @CanActivate 1. 시점 : Routing이 되기 직전.(angular1의 resolve) 2. 용도 : Login/Auth 체크시 많이 사용된다. 3. return : true이면 Routing이 되며, false이면 Routing이 취소된다.
  • 23. Routing & Navigation routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) { this.log = `Finished navigating from "${prev ? prev.urlPath : 'null'}" to "${next.urlPath}"`; console.log(this.log); /* Routing이 완료되어 구성되자마자 실행이 된다. */ return new Promise(resolve => { setTimeout(() => resolve(null), 1000); }); } onActivate 1. 시점 : Routing 완료되어 구성되자마자 실행 2. return : promise를 통해서 리턴이되며 해당 promise가 될때까지 기다린다.
  • 24. Routing & Navigation routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any { if (!this.crisis || this.crisis.name === this.editName) { return true; } return this._dialog.confirm('Discard changes?'); } onActivate 1. 시점 : 해당 Route에서 다른 Route로 이동할 때 된다.(이동하기 바로전) 2. return : true이면 이동이되며, false면 이동이 안된다.
  • 25. Routing & Navigation @CanActivate((next, prev) => { console.log(`CanActivate`); return true }) export class CrisisDetailComponent implements OnInit, CanDeactivate { constructor() { console.log(`constructor`); } ngOnInit() { console.log(`ngOnInit`); } routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) { console.log(`OnActivate`); /* Routing이 완료되어 구성되자마자 실행이 된다. */ return new Promise(resolve => { setTimeout(() => resolve(null), 1000); }); } routerCanDeactivate(next: ComponentInstruction, prev: ComponentInstruction) : any { if (!this.crisis || this.crisis.name === this.editName) { return true; } return this._dialog.confirm('Discard changes?'); } } 출력 되는 순서 1. CanActivate 2. constructor 3. OnActivate 4. ngOnInit
  • 26. Routing & Navigation 해당 라우터로 이동시에 <a [routerLink]="['CrisisCenter']"> 위와 같이 선언이 되어 있는 부분에 해당 라우터를 호출을 하면 아래와 같이 자동으로 class를 부여한다. <a href="/crisis-center" class="router-link-active">
  • 27. Routing & Navigation 상세 아래와 같이 부모 자식간의 관계가 아닌 같은 노드의 다른 라우터이기 때문에 heroes의 상세에 들어가도 Heroes에 class가 부여되지 않는다. 서로 다른 라우터로 인식하기 때문이다. {path: '/heroes', name: 'Heroes', component: HeroListComponent}, {path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
  • 28. Routing & Navigation 상세 아래와 같이 부모와 자식관계이기 때문에 class가 부여된다. 부모 { path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent, useAsDefault: true } 자식 {path:'/', name: 'CrisisList', component: CrisisListComponent, useAsDefault: true}, {path:'/:id', name: 'CrisisDetail', component: CrisisDetailComponent}
  • 29. 예제 소스 Http - https://github.com/mayajuni/angular2-http Routing & Nav - https://github.com/mayajuni/angular2-routing-nav