SlideShare a Scribd company logo
1 of 29
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

Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
yongwoo Jeon
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
정석 양
 

What's hot (20)

진짜기초 Node.js
진짜기초 Node.js진짜기초 Node.js
진짜기초 Node.js
 
ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는
 
Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트Angular2를 위한 타입스크립트
Angular2를 위한 타입스크립트
 
[11]Android DataBinding : 기초에서 고급까지
[11]Android DataBinding : 기초에서 고급까지[11]Android DataBinding : 기초에서 고급까지
[11]Android DataBinding : 기초에서 고급까지
 
Redux
ReduxRedux
Redux
 
Protocol Oriented Programming in Swift
Protocol Oriented Programming in SwiftProtocol Oriented Programming in Swift
Protocol Oriented Programming in Swift
 
Web Components 101 polymer & brick
Web Components 101 polymer & brickWeb Components 101 polymer & brick
Web Components 101 polymer & brick
 
Html5 web workers
Html5 web workersHtml5 web workers
Html5 web workers
 
Startup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JSStartup JavaScript 8 - NPM, Express.JS
Startup JavaScript 8 - NPM, Express.JS
 
Express 프레임워크
Express 프레임워크Express 프레임워크
Express 프레임워크
 
AngularJS의 개발방식에 대하여
AngularJS의 개발방식에 대하여AngularJS의 개발방식에 대하여
AngularJS의 개발방식에 대하여
 
처음배우는 자바스크립트, 제이쿼리 #1
처음배우는 자바스크립트, 제이쿼리 #1처음배우는 자바스크립트, 제이쿼리 #1
처음배우는 자바스크립트, 제이쿼리 #1
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
 
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modificationSecrets of the JavaScript Ninja - Chapter 12. DOM modification
Secrets of the JavaScript Ninja - Chapter 12. DOM modification
 
Node.js intro
Node.js introNode.js intro
Node.js intro
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Web workers
Web workersWeb workers
Web workers
 
Dependency Injection 소개
Dependency Injection 소개Dependency Injection 소개
Dependency Injection 소개
 
파이썬 언어 기초
파이썬 언어 기초파이썬 언어 기초
파이썬 언어 기초
 

Viewers also liked

Viewers also liked (20)

RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015RxJS and Reactive Programming - Modern Web UI - May 2015
RxJS and Reactive Programming - Modern Web UI - May 2015
 
Angular2
Angular2Angular2
Angular2
 
Angular2 inter3
Angular2 inter3Angular2 inter3
Angular2 inter3
 
Authentication and Authorization Architecture in the MEAN Stack
Authentication and Authorization Architecture in the MEAN StackAuthentication and Authorization Architecture in the MEAN Stack
Authentication and Authorization Architecture in the MEAN Stack
 
Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1
 
Adventures with Angular 2
Adventures with Angular 2Adventures with Angular 2
Adventures with Angular 2
 
How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!
 
Angular2 - getting-ready
Angular2 - getting-ready Angular2 - getting-ready
Angular2 - getting-ready
 
Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발Angular2를 활용한 컴포넌트 중심의 개발
Angular2를 활용한 컴포넌트 중심의 개발
 
Angular2 workshop
Angular2 workshopAngular2 workshop
Angular2 workshop
 
Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까
 
Cascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the StreamsCascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the Streams
 
Angular 2 - Core Concepts
Angular 2 - Core ConceptsAngular 2 - Core Concepts
Angular 2 - Core Concepts
 
Functional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwiftFunctional Reactive Programming With RxSwift
Functional Reactive Programming With RxSwift
 
Introduction to Angular 2
Introduction to Angular 2Introduction to Angular 2
Introduction to Angular 2
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
Getting Started with Angular 2
Getting Started with Angular 2Getting Started with Angular 2
Getting Started with Angular 2
 
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
NDC14 - Rx와 Functional Reactive Programming으로 고성능 서버 만들기
 

Similar to Angular2 router&http

vine webdev
vine webdevvine webdev
vine webdev
dcfc1997
 
Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)
Sungjoon Yoon
 

Similar to Angular2 router&http (20)

Nodejs express
Nodejs expressNodejs express
Nodejs express
 
vine webdev
vine webdevvine webdev
vine webdev
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
Xe hack
Xe hackXe hack
Xe hack
 
Node.js and react
Node.js and reactNode.js and react
Node.js and react
 
막하는스터디 두번째만남 Express(20151025)
막하는스터디 두번째만남 Express(20151025)막하는스터디 두번째만남 Express(20151025)
막하는스터디 두번째만남 Express(20151025)
 
파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄 파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄
 
JSP 프로그래밍 #03 서블릿
JSP 프로그래밍 #03 서블릿JSP 프로그래밍 #03 서블릿
JSP 프로그래밍 #03 서블릿
 
Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)
 
One-day-codelab
One-day-codelabOne-day-codelab
One-day-codelab
 
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#22.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
 
Nest js 101
Nest js 101Nest js 101
Nest js 101
 
[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVC[스프링 스터디 3일차] @MVC
[스프링 스터디 3일차] @MVC
 
4-3. jquery
4-3. jquery4-3. jquery
4-3. jquery
 
자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)
자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)
자바 웹 개발 시작하기 (3주차 : 스프링 웹 개발)
 
4-2. ajax
4-2. ajax4-2. ajax
4-2. ajax
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
 
자바스크립트 클래스의 프로토타입(prototype of class)
자바스크립트 클래스의  프로토타입(prototype of class)자바스크립트 클래스의  프로토타입(prototype of class)
자바스크립트 클래스의 프로토타입(prototype of class)
 
Multithread programming 20151206_서진택
Multithread programming 20151206_서진택Multithread programming 20151206_서진택
Multithread programming 20151206_서진택
 

Recently uploaded

Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)
Wonjun Hwang
 

Recently uploaded (7)

캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and Adoption[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and Adoption
 
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
 

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