Goalist Developers Blog

はじめてのAngular TODOアプリをつくる④ HTTP編

どうも、イイオです。
AngularでTODOアプリ的なものを作ってみようシリーズ、
チュートリアルでいうとこの辺りを見つつ、通信の部分やってきます。

https://angular.io/tutorial/toh-pt6

前回まで一体何をやっていたんだ?漢は過去に拘泥しない。

目標

今回のゴールは「HTTP通信してWebAPIを呼び出し、データのやり取りを行う」ことです。
でその際に
チュートリアルではObservableに包まれて来るレスポンスを.toPromise()でPromiseに変換してるけど
Observableをそのまま使うのがゴーリストではスタンダードっぽいのでそれに準じてます。

やること

  1. InMemoryWebApiModuleを使ってAPIサーバ風にふるまってもらう準備
  2. Observableを使ってHTTP通信する

1. InMemoryWebApiModuleを使ってAPIサーバ風にふるまってもらう準備

Webサーバのシミュレーションしてくれる機構が用意されています。

なぜか入ってなかったのでnpmで取ってきた

npm install angular-in-memory-web-api@latest

angular2の場合はangular2-in-memory-web-apiかもしれない

DBのふりするサービスを作成

ng g service in-memory-data

mock-tasks.tsからモックデータをコピってきて中身はこんなかんじに

in-memory-data.service.ts

import { Injectable } from '@angular/core';
import { InMemoryDbService } from 'angular-in-memory-web-api';

@Injectable()
export class InMemoryDataService implements InMemoryDbService {

  constructor() { }

  public createDb() {
    const tasks = [
      { id: 0, name: '', importance: 'high', isDone: false },
      { id: 11, name: '企画ロードマップ作成', importance: 'high', isDone: false },
      { id: 12, name: '山田さんにメール返信', importance: 'high', isDone: false },
      { id: 13, name: 'Angular2キャッチアップ', importance: 'mid', isDone: false },
      { id: 14, name: 'ブログ更新', importance: 'low', isDone: false },
      { id: 15, name: '新卒技術研修', importance: 'low', isDone: false }
    ];
    return tasks;
  }

}

http://localhost:4200/api/tasksをエンドポイントにGETすると
Response.json().dataでこの配列が返って来る。なんでか知らないけど返って来る。
わからなくても使えればいいんだなあ いいを

このサービスをapp.module.tsに登録して使えるようにする

import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService }  from './in-memory-data.service';
・・・
@NgModule({
  imports: [
    ・・・
    InMemoryWebApiModule.forRoot(InMemoryDataService),
  ],
  ・・・
})

2. Observableを使ってhttp通信する

とりあえず全データ取得するやつをちゃんと動くようにしてみようかと。
前々回くらいに作ったTaskサービスを書き換えます。

task.service.ts

import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';

@Injectable()
export class TaskService {
  private headers: Headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) { }

  public getTasks(): Observable<Task[]> {
    const url = 'api/tasks';
    return this.http.get(url, {headers: this.headers})
      .switchMap((response: Response) => {
        return Task.toTasks(response.json().data); // チュートリアルみたいに as Task[] ではキャストできなかった
      })
      .catch((error) => {
        throw new Error(error); // なんかエラー出たら呼び出し元の方でで受け取ってもらう
      });
  }
  
}

そうしてObservableにくるんだオブジェクトを呼び出し元に返してあげる。
呼び出し元ではObservableで返ってきたオブジェクトをsubscribeしたら使える状態になります。

export class TasksComponent implements OnInit {
  private tasks: Task[];

  constructor(private taskService: TaskService) { }

  ngOnInit() {
    this.getTasks();
  }

  private getTasks(): void {
    this.taskService.getTasks()
      .subscribe(
        (retTasks: Task[]) => {
          console.log(retTasks);
          this.tasks = retTasks;
        },
        (error: any) => {
          console.log(error);
        }
      );
  }

}

よし!!!!目標達成!!!!!
同様にしてデータ作成・更新・削除のメソッドを作れば完成!!!
大胆にも割愛する勇気ッ!!!ソイヤッソイヤッ

はい

というわけで、Observableからのsubscribeする流れの一例として見ていただければと思います。

Q. TODOアプリ完成させないんですか?
A. 完全性は地獄に置いて来た

誰の役にも立たないものを作るのはつらい。自分のためか。
とはいえ新卒も加入してどんどこ更新してくれるらしいのでエンジニアブログの未来は明るい。
明るい!

はい

最近業務でWebアプリをリリースしました。
チュートリアルを完走する前に本番の締切が来た。
フロントはAngularによって書かれています。できたてホカホカです。

map.hrog.net

企画とかからやらしてもらってます。

イベント告知

2017年7月21日(金) 19:30〜21:30、ゴーリスト東京本社にて
AWS Lambdaを中心に、サーバレスアーキテクチャを勉強する会
が開催されます!

connpass.com

このブログでもシチメンロッピの活躍中の盛次さんが登壇します。
すでに席はかなり埋まってしまっていますが、ご興味あればぜひ٩( ‘ω’ )و

はい

そんなかんじです