ng g s hero
로 Hero.service.ts 파일 생성
@Injectable 데코레이터는 해당 클래스가 의존성 주입 시스템에 포함이 되었다. 그래서 다른 컴포넌트 등에서 의존성으로 주입받을수 있으며 , 이 클래스도 의존성을 주입 받을 수 있다.
// src/app/service/hero.service.ts
import { Injectable } from '@angular/core';
import { HEROES } from '../mock';
import { Hero } from '../model/data';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor() {}
getHeroes(): Hero[] {
return HEROES;
}
}
생성한 HeroService 타입의 heroService 인자를 생성하고 이 인자를 private로 지정합니다.
constructor(private heroService: HeroService) {
this.getHeroes();
}
Angular 가 해당 HeroComponent를 생성할 때 의존성 주입 시스템이 HeroService의 인스턴스를 찾아서 heroService 라는 인자에 전달하여 의존성을 주입한다.
// src/app/component/heroes/heroes.component.ts
import { Component, OnInit } from '@angular/core';
import { HSModel } from 'src/app/model';
import { HeroService } from 'src/app/service/hero.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.scss'],
})
export class HeroesComponent implements OnInit {
heroes: HSModel.Hero[] = [];
selectedHero?: HSModel.Hero;
constructor(private heroService: HeroService) {
this.getHeroes();
}
ngOnInit(): void {}
onSelect(hero: HSModel.Hero): void {
this.selectedHero = hero;
}
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
}
실제로는 데이터를 서버에서 가져온다. 서버에서 데이터를 가져오는 경우에는 비동기로 동작하여 데이터를 가져와야 하기에 this.heroes = this.heroService.getHeroes();
문구는 비동기로 동작해야 한다.
Angular가 제공하연 HttpClient.get 메소드는 Observable 을 반환한다.
// src/app/service/hero.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HEROES } from '../mock';
import { Hero } from '../model/data';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor() {}
// 실제 동작은 서버에 요청을 하여 데이터를 받아오므로
// 비동기로 동작하기에 Observable 타입으로 설정한다.
getHeroes(): Observable<Hero[]> {
const heroes = of(HEROES);
return heroes;
}
}
this.heroService.getHeroes() 함수가 서버에 요청을 하여 데이터를 받기에 Observable 타입을 반환하는데, 반환 시점은 함수를 실행한 직후 일 수도 있고 몇분 후일수도 있습니다.
비동기적으로 응답이 도착했을떄 subscribe가 응답을 콜백함수로 전달하고, 콜백 함수에서 응답을 this.heroes 와 같은 필요한 프로퍼티에 할당합니다.
// src/app/component/heroes/heroes.component.ts
import { Component, OnInit } from '@angular/core';
import { HSModel } from 'src/app/model';
import { HeroService } from 'src/app/service/hero.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.scss'],
})
export class HeroesComponent implements OnInit {
heroes: HSModel.Hero[] = [];
selectedHero?: HSModel.Hero;
constructor(private heroService: HeroService) {
this.getHeroes();
}
ngOnInit(): void {}
onSelect(hero: HSModel.Hero): void {
this.selectedHero = hero;
}
getHeroes(): void {
this.heroService.getHeroes().subscribe((heroes) => (this.heroes = heroes));
}
}
messages 컴포넌트 생성하기
message 서비스 생성하기
// src/app/service/message.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MessageService {
messages: string[] = [];
constructor() {}
add(message: string): void {
this.messages.push(message);
}
clear(): void {
this.messages = [];
}
}
A 서비스 안에 B 서비스 존재(사용)하는 경우
// src/app/service/hero.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HEROES } from '../mock';
import { Hero } from '../model/data';
import { MessageService } from './message.service';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor(private messageService: MessageService) {}
getHeroes(): Observable<Hero[]> {
const heroes = of(HEROES);
this.messageService.add('HeroService : fetched heroes(데이터를 불러옴)');
return heroes;
}
}
MessageComponet
에다가 MessageService
프로퍼티를 바인딩한다. 의존성 주입이 아니다!! 바인딩하는 것이다.!!!! public 을 사용한다.
// src/app/component/messages/messages.component.ts
import { Component, OnInit } from '@angular/core';
import { MessageService } from 'src/app/service/message.service';
@Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.scss'],
})
export class MessagesComponent implements OnInit {
constructor(public messageService: MessageService) {}
ngOnInit(): void {}
}
바인딩하였기에 MessageService의 프로퍼티 및 함수를 사용한다.
// src/app/component/messages/messages.component.html
<div *ngIf="messageService.messages.length">
<h2>Messages</h2>
<button class="clear" (click)="messageService.clear()">Clear messages</button>
<div *ngFor="let message of messageService.messages">{{ message }}</div>
</div>
히어로를 선택했을때 이에 대한 메시지를 표현하기 위하여 선택했을떄 동작하는 함수에 MessageService 를 이용하자.
// src/app/component/heroes/heroes.component.ts
import { Component, OnInit } from '@angular/core';
import { HSModel } from 'src/app/model';
import { HeroService } from 'src/app/service/hero.service';
import { MessageService } from 'src/app/service/message.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.scss'],
})
export class HeroesComponent implements OnInit {
heroes: HSModel.Hero[] = [];
selectedHero?: HSModel.Hero;
constructor(
private heroService: HeroService,
private messageService: MessageService
) {
this.getHeroes();
}
ngOnInit(): void {}
onSelect(hero: HSModel.Hero): void {
this.selectedHero = hero;
this.messageService.add(
`HeroesComponent : Selected hero id=${hero.id}, name=${hero.name}`
);
}
getHeroes(): void {
this.heroService.getHeroes().subscribe((heroes) => (this.heroes = heroes));
}
}