반응형

옵저버블 데이터

HeroService.getHeroes() 메소드는 동기 특성을 가진다, 어느 HeroService 동시에 가지고 올수 있는것을  넌지시 나타낸다. HeroesComponent는 영웅들을 동시적으로 가져온는것을 하는 것처럼 getHeroes() 결과를 사용한다.

this.heroes = this.heroService.getHeroes();

실제 앱에선 동작할수 없다. 이제 서비스가 현재 리턴하는 가짜 영웅들을에게 떠난다. 하지만 곧 앱은 영웅들을 원격 서버에서 가져올수 있다. 그것은 선천적으로 동시적인 연산이다.

HeroService는 서버의 응답을 기야려야만 한다.  getHeroes() 영웅 데이터 리턴을 즉각적으로 할수 없다.  브라우저는  그 서비스가 기다리는 동안의 차단되지 않을 것이다.           

HeroService.getHeroes()는 어떤 종류의 비동기특성을가져야 한다.

그것은 응답을 가질수있다. 그것은 리턴을 약속합니다. 그것은 관찰할수 있는것을 리턴할수 잇다.

이 튜토리얼에서  HeroService.getHeroes()는 이 부분에서 관찰가능한것을 리턴할수 있습니다. 왜냐하면 결국 영웅들을 가져오기 위해 앵귤라 HttpClient.get 메소드를 사용 하는것일 것이다. HttpClient.get()은 관찰 가능함을 리턴한다.


옵저버블한 HeroService 

옵저버블은 RxJS라이브러리에서 키 클래스들중의 하나이다.

나중에 HTTP 튜토리얼에서, 앵귤라의 HttpClient 메소드가 RxJS 옵저버블을 리턴하는것을 배울수 있습니다. 이번 튜토리얼은 RxJS의 of() 기능을 통해 서버에서 데이터를 갖는것을 가장할것이다.

HeroService 파일을 열어 Observable 과 RxJS 기호를 Import 합니다.

src/app/hero.service.ts (Observable imports)

import { Observable } from 'rxjs/Observable';

import { of } from 'rxjs/observable/of';

getHeroes 메소드를 아래처럼 변경합니다.

getHeroes(): Observable<Hero[]> {

  return of(HEROES);

}

of(HEROES)은  가짜 영웅 배열의 하나의 값을 내는  Observable<Hero[]>  리턴합니다. 

HTTP 튜토리얼에서 HttpClient.get<Hero[]>()을 호출 할것이다.   또한 Observable<Hero[]>은  HTTP 응답 내용에서 영웅 배열에 하나의값을 나타내는 것을 리턴합니다.


HeroesComponent 구독

HeroService.getHeroes 메소드는 Hero[]을 리턴 하곤 했다. 지금은 Observable<Hero[]>을 리턴한다.

HeroesComponent에서의 차이를 적응 해야만 합다.

getHeroes 메소드를 찾아  다음 코드와 함께 변경합니다. ( 이번전번과 비교를 위해 나라히 보면서 )

heroes.component.ts (Observable)

getHeroes(): void {

  this.heroService.getHeroes()

      .subscribe(heroes => this.heroes = heroes);

}

heroes.component.ts (Original)

getHeroes(): void {

  this.heroes = this.heroService.getHeroes();

}

Observable.subscribe()는 주요변화이다.

이전 버전은 영웅들의 배열을 콤포넌트의 영웅들의 속성으로 배정합니다. 동시에 일어나는 배정은, 서버에 즉시 영웅 정보를 리턴하는것처럼  혹은  브라우저 UI가 서버의 응답을 기다리는동안 멈춰 질수 있다.

HeroService는 원격 서버에서 실제로 요청을 만들 작업하지 않을것이다.

새로운 버전은 옵저버블되어 나타난 영웅들의 배열을 ( 지금 일어날수 있거나 지금에서 부터 몇분간  ) 기다린다.  그리고는 콜백으로 나타난 배열 구독을 통과한다. 컴포넌트의 영웅 속성의 어떤 설정을 합니다.

동시에 다가가것은 HeroService가 서버에서 영웅들을 요청할때 동작 할수 있다.


메세지를 보자

이번섹션에서는 할것들

  • 화면 아래에 앱메세지가 표시될 MessagesComponent를  추가한다.
  • injectable을 생성한다. 앱 전체의 MessageService는 표시되게 메세지를 보낸다.
  • HeroService으로 MessageService를 주입한다.
  • 메세지가 표시될때 HeroService는 영웅들을 성공적으로 가지고 온다.


MessagesComponent 생성

MessagesComponent를 CLI 사용해서 생성합니다.

ng generate component messages

CLI 은 src/app/messages 폴더 안에 컴포넌트 파일을  만들고 AppModule 안에 MessagesComponent를 선언 합니다.

AppComponent 템플릿을 자동생성된 MessagesComponent를 화면에 보이는것을 수정한다.


/src/app/app.component.html

<h1>{{title}}</h1>

<app-heroes></app-heroes>

<app-messages></app-messages>

이페이지 아래에 있는 MessagesComponent에서 기본 단락을  보아야 한다.


MessageService 생성

MessageService를  src/ap 안에 CLI을 사용해서 생성한다. --module=app 옵션은 CLI이 AppModule안에 서비스를 제공하기위함을  알려준다.

ng generate service message --module=app

MessageService 열고 다음처럼 내용을 변경한다.


/src/app/message.service.ts

import { Injectable } from '@angular/core';


@Injectable()

export class MessageService {

  messages: string[] = [];


  add(message: string) {

    this.messages.push(message);

  }


  clear() {

    this.messages = [];

  }

}


서비스 캐쉬된 메세지와 두개위 모듈을 드러낸다.  메세지가 캐시로된 add()와 다른 캐시에 그캐시를 clear()한다.


HeroService에 주입하기.

HeroService 다시열고 MessageService를 Import 한다.

/src/app/hero.service.ts (import MessageService)

import { MessageService } from './message.service';

선언한 private messageService 속성 생성자와 파라메터를 수정한다. HeroService가 생성될때  앵귤라는 싱글톤 MessageService를 그 속성에  주입할수 있다.

constructor(private messageService: MessageService) { }

전형적인 "service-in-service" 시나리오 : MessageService를 HeroService에  주입한는것은  HeroesComponent에 주입된것이다.


HeroService에서 메세지 보내기

getHeroes 메소드로 메세지를 보낼때 영웅을 가져오게  수정한다.

getHeroes(): Observable<Hero[]> {

  // Todo: send the message _after_ fetching the heroes

  this.messageService.add('HeroService: fetched heroes');

  return of(HEROES);

}


HeroService에서 메세지를 표시

MessagesComponent는 모든 메세지를 표시 해야하며, 영웅들을 가져올때 포함된는 그 메세지는 HeroService로 보낸다.

MessagesComponent을 열고 MessageService를 import 한다.

/src/app/messages/messages.component.ts (import MessageService)

import { MessageService } from '../message.service';

생성자를 파라메터와 함깨  선언한 공개  messageService 속성을 수정한다. 앵귤라는 HeroService가 생성될때 싱글톤 MessageService를 그 속성에  주입할수 있다.

constructor(public messageService: MessageService) {}

messageService 속성은 public 으로 해야만 하는 이유는 이 템플릿에서 바인딩하기 때문이다.

앵귤라 단순히 public 된 컴포넌트 속성을 바인드한다.


MessageService 바인드

CLI은 자동생성된  MessagesComponent 템플릿을 다음처럼 변경한다. 

src/app/messages/messages.component.html

<div *ngIf="messageService.messages.length">

  <h2>Messages</h2>

  <button class="clear"

          (click)="messageService.clear()">clear</button>

  <div *ngFor='let message of messageService.messages'> {{message}} </div>

</div>

템플릿은 컴포넌트의 messageService로 직접 바인된다. 

*ngIf은 단지 메세지가 표시될때면 메세지 영역에 표시 하기만 한다. 

*ngFor 는 <div> 요소가 반복속에  메세지의 목록을 부여한다.

Angular는 버튼의 클릭 이벤트를 MessageService.clear()로 이벤트 구속력 있게 바인드한다.

메세지는 사적인 CSS 스타일을  messages.component.css에 추가 했을때 더 좋아 보일수 있다. 

브라우저가 재생되고 영웅들의 목록이 페이지에서 표시된다.  아래로 스크롤릴  하면  메세지 영역안의 HeroService에서 온 메세지를 본다 . "clear"버튼을 크릭하면 메세지 영역을 사라지게 한다.


요약

  • 리팩토리된 HeroService 클래스로 데이터를 접근한다.
  • 제공된어진 HeroService는 root AppModule에서 어디에서나 주입될수 있다.
  • 컴포넌트 안으로 주입하는것을 Angular Dependency Injection을  사용 한다.
  • HeroService get data 메소드에 비동기 특성을 지정 했다.
  •  Observable 과 RxJS Observable library를 발견 했다.
  • 가짜 영웅이 Observable이 리턴되는  RxJS of() 사용했다.
  • 콤포넌트의 라이프사이클 hook는 생성자가 아니고 ngOnInit에서    HeroService 메소드를 호출한다. 
  • 클래스 사이의 약결합 통신인  MessageService 생성했다.
  • HeroService는 컴포넌트에  주입되어진다.다른 주입된 서비스는 MessageService 로 생성된다.


반응형

+ Recent posts