제8회: 뉴스 피드 취득 서버 IF를 웹 앱에서 호출
7825 단어 Angular
제8회: 뉴스 피드 취득 서버 IF를 웹 앱에서 호출
이번에는 이전에 작성한 뉴스 피드 목록 취득 IF를 프런트 엔드에서 호출해 보겠습니다.
REST API 조작을 위한 서비스 작성
빈 서비스 만들기
프런트 엔드에서 REST API를 처리하는 서비스를 만듭니다.
다음 명령을 실행합니다.
$ ng g service services/rest/rest
rest.service.ts
및 테스트 코드 rest.service.spec.ts
가 만들어집니다.
모듈에서 만든 서비스 로드
src/app/app.module.ts
에서 다음을 수정하여 앱에 service를 로드합니다.
・・・
import { RestService } from './services/rest/rest.service';
・・・
providers: [
RestService
],
・・・
REST API의 응답 데이터를 수신하기 위한 데이터 클래스 작성
뉴스피드용 데이터 클래스 만들기
src/app/services/rest/data/newsfeeds.ts
를 다음과 같이 새로 작성합니다.
뉴스피드의 데이터를 갖게 하기 위한 데이터 클래스입니다.
export class Newsfeed {
message: string;
createdAt: Date;
decode(json: any) {
if (json) {
this.message = json.message;
this.createdAt = json.createdAt ? new Date(json.createdAt) : undefined;
}
}
}
export class Newsfeeds {
private sortedByDefault: Newsfeed[] = [];
newsfeeds: Newsfeed[];
decode(json: any) {
if (json) {
for (const jsonNewsfeed of json) {
const newsfeed = new Newsfeed();
newsfeed.decode(jsonNewsfeed);
this.sortedByDefault.push(newsfeed);
}
this.sortByCreatedAt();
}
}
sortByCreatedAt() {
this.newsfeeds = this.sortedByDefault.slice();
this.newsfeeds.sort((a, b) => {
return b.createdAt.getTime() - a.createdAt.getTime();
});
}
}
JSON 객체로부터 데이터를 꺼내, 내부에 보관 유지시키는 decode 메소드나,
일시로 초기 소트를 실시하는 sortByCreatedAt() 메소드를 갖게 하고 있습니다.
응답 데이터 공통 데이터 클래스 만들기
src/app/services/rest/data/response.ts
를 다음과 같이 새로 작성합니다.
모든 응답 데이터가 공통으로 가지는 부분을 작성합니다.
export class Response<T> {
code: number;
data: T;
constructor(data: T, code?: number) {
this.code = code ? code : 200;
this.data = data;
}
}
RestService에서 뉴스 피드 목록을 얻기위한 처리 구현
HttpClientModule을 모듈에 등록
RestClient에서는 HttpClient를 사용하고 싶으므로 HttpClientModule을 app.module.ts
에 등록합니다.
・・・
import { HttpClientModule } from '@angular/common/http';
・・・
imports: [
・・・
HttpClientModule,
],
・・・
RestService에서 뉴스 피드 목록 검색 처리 구현
src/app/services/rest/rest.service.ts
에서 뉴스 피드 목록 검색 처리를 구현합니다.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Response } from './data/response';
import { Newsfeeds } from './data/newsfeeds';
@Injectable({
providedIn: 'root'
})
export class RestService {
constructor(
private httpClient: HttpClient
) { }
async searchNewsFeeds(): Promise<Response<Newsfeeds>> {
return new Promise((resolve, reject) => {
const url = 'http://127.0.0.1:4300/newsfeeds';
this.httpClient.get(url).toPromise().then(response => {
const newsfeeds = new Newsfeeds();
newsfeeds.decode(response);
resolve(new Response(newsfeeds));
}).catch(error => {
console.error(error);
reject(error);
});
});
}
}
async, Promise, resolve, reject, then, catch는 비동기 처리를 수행하기 위한 것입니다.
아래를 참조하십시오.
$ ng g service services/rest/rest
・・・
import { RestService } from './services/rest/rest.service';
・・・
providers: [
RestService
],
・・・
export class Newsfeed {
message: string;
createdAt: Date;
decode(json: any) {
if (json) {
this.message = json.message;
this.createdAt = json.createdAt ? new Date(json.createdAt) : undefined;
}
}
}
export class Newsfeeds {
private sortedByDefault: Newsfeed[] = [];
newsfeeds: Newsfeed[];
decode(json: any) {
if (json) {
for (const jsonNewsfeed of json) {
const newsfeed = new Newsfeed();
newsfeed.decode(jsonNewsfeed);
this.sortedByDefault.push(newsfeed);
}
this.sortByCreatedAt();
}
}
sortByCreatedAt() {
this.newsfeeds = this.sortedByDefault.slice();
this.newsfeeds.sort((a, b) => {
return b.createdAt.getTime() - a.createdAt.getTime();
});
}
}
export class Response<T> {
code: number;
data: T;
constructor(data: T, code?: number) {
this.code = code ? code : 200;
this.data = data;
}
}
・・・
import { HttpClientModule } from '@angular/common/http';
・・・
imports: [
・・・
HttpClientModule,
],
・・・
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Response } from './data/response';
import { Newsfeeds } from './data/newsfeeds';
@Injectable({
providedIn: 'root'
})
export class RestService {
constructor(
private httpClient: HttpClient
) { }
async searchNewsFeeds(): Promise<Response<Newsfeeds>> {
return new Promise((resolve, reject) => {
const url = 'http://127.0.0.1:4300/newsfeeds';
this.httpClient.get(url).toPromise().then(response => {
const newsfeeds = new Newsfeeds();
newsfeeds.decode(response);
resolve(new Response(newsfeeds));
}).catch(error => {
console.error(error);
reject(error);
});
});
}
}
REST API는
this.httpClient.get(url)
부분에서 호출됩니다.구성 요소에서 만든 RestService 사용
TypeScript 파일을 수정합니다.
src/app/components/newsfeeds/newsfeeds.component.ts
를 다음과 같이 수정합니다.후술하는 html의 수정까지 실시하지 않으면 에러가 됩니다.
import { Component, OnInit } from '@angular/core';
import { RestService } from '../../services/rest/rest.service';
import { Newsfeeds } from '../../services/rest/data/newsfeeds';
@Component({
selector: 'app-newsfeeds',
templateUrl: './newsfeeds.component.html',
styleUrls: ['./newsfeeds.component.scss']
})
export class NewsfeedsComponent implements OnInit {
newsfeeds: Newsfeeds;
constructor(
private restService: RestService
) { }
async ngOnInit() {
try {
const response = await this.restService.searchNewsFeeds();
this.newsfeeds = response.data;
} catch (error) {
// TODO: display alert dialog.
}
}
}
Service 객체는 앱 내에서 하나만 생성됩니다.
constructor()의 인수에 Service를 기재하는 것으로, 컴퍼넌트가 생성될 때 인수에 건네집니다.
constructor(
private restService: RestService
) { }
aync, await는 비동기입니다.
비동기 처리 async, await 정보을 참조하십시오.
HTML 파일을 수정합니다.
src/app/components/newsfeeds/newsfeeds.component.html
를 다음과 같이 수정합니다.여기까지 구현하면, 화면에 백엔드로부터 취득한 데이터가 표시됩니다.
<div id="newsfeeds">
<ng-container *ngIf="newsfeeds && newsfeeds.newsfeeds">
<article *ngFor="let newsfeed of newsfeeds.newsfeeds" class="newsfeed">
<p class="message">{{newsfeed.message}}</p>
<p class="createdAt">{{newsfeed.createdAt | dateToString}}</p>
</article>
</ng-container>
</div>
원래는 newsfeeds에 배열을 갖게 하고 있었지만, newsfeeds.newsfeeds에 배열을 갖게하도록 수정하고 있습니다.
따라서 REST API에서 데이터를 받기 전에 화면을 만들려고하면 newsfeeds.newsfeeds에 참조 오류가 발생합니다.
따라서 if 문을 추가하고 데이터가 있을 때만 표시하도록 수정하고 있습니다.
또한
*ngIf
는 *ngFor
와 동일한 태그에 쓸 수 없으므로 <ng-container>
를 추가하고 *ngIf
를 수행합니다.<ng-container>
는 화면에 표시되지 않는 제어용 태그입니다.환경 변수 이용
환경 파일 수정
src/app/services/rest/rest.service.ts
에 서버 주소 http://127.0.0.1:4300
를 직접 작성했기 때문에,환경 변수로 바꿉니다.
src/environments/environment.prod.ts
및 src/environments/environment.ts
에 아래의 부분을 추가합니다.export const environment = {
production: true,
rest: {
domain: 'http://127.0.0.1:4300'
}
};
environment.prod.ts
는 프로덕션 (상용) 빌드이고 environment.ts
는 개발 빌드에서 사용되는 환경 변수입니다.지금까지 사용해 온 빌드 명령
$ ng serve
이나 $ ng build
는 개발용의 빌드를 실시합니다.--prod
옵션을 사용하면 프로덕션 빌드가됩니다.환경 변수 포함
src/app/services/rest/rest.service.ts
에 다음 수정 사항을 추가합니다.・・・
import { environment } from '../../../environments/environment';
・・・
async searchNewsFeeds(): Promise<Response<Newsfeeds>> {
return new Promise((resolve, reject) => {
const url = environment.rest.domain + '/newsfeeds';
・・・
마지막으로
이번에는 프런트 엔드에서 REST API를 불러 보았습니다.
다음 번에는 뉴스 피드 게시물에 대한 IF를 만들겠습니다.
이번에 개발한 소스 코드는 GitHub에 들어 있습니다.
Reference
이 문제에 관하여(제8회: 뉴스 피드 취득 서버 IF를 웹 앱에서 호출), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/radiance1104/items/fd3e8153c8676d3de07e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)