HttpClientサービスを使ってWeb APIと非同期通信するための基本的な方法を説明する。
※現在では、Web標準技術を利用したアプリ開発が広く普及し、そのためのフレームワークも多数存在しています。その中でも主流のフレームワークの1つである「Angular」を活用し、そのための知識を備えることには大きな意味があります。本連載は、Angularユーザーに向けて、その使いこなしTIPSを紹介するものです。なお、本連載は「Build Insider」で公開していた連載「Angular Tips」を同サイトおよび筆者の了解を得たうえで、本フォーラムに移行したものです。記事はBuild Insiderで公開した状態のまま移行しているため、用語統一などの基準が@ITの通常の記事とは異なる場合があります。
Angular 5以降。v5時点で執筆しました。
近年のフロントエンド開発において、非同期通信を受け持つXMLHttpRequest(XHR)オブジェクトは欠かせません。JavaScript単体でできることは限られています。JavaScriptアプリでは、ページ上の操作に応じてXHRでサーバーに処理を要求し、その処理結果をページに反映させるのが基本です*1。
*1 このようなアプリのことを、単一のページで全ての処理を完結させることから、SPA(Single Page Application)と呼びます。
HttpClientサービス*2は、このXHRオブジェクトのラッパーです。HttpClientサービスを利用することで、XHRオブジェクトでは冗長になりがちだった通信の手続きを、よりシンプルに記述できるようになります。
*2 以前は@angular/httpモジュールに属するHttpサービスがありましたが、Angular 5では非推奨の扱いとなっています。今後はHttpClientサービスを優先して利用してください。
HttpClientサービスは、実にさまざまな機能(パラメーター)を持っていますが、本稿ではまず、HttpClientサービスを利用した基本的な非同期通信の手続きについて解説します。
さっそく、具体的な例を見ていきましょう。以下は、テキストボックスに入力された名前に応じて、サーバーから「Hello, ●○!」のようなメッセージを受け取り、表示するサンプルです。
(1)HttpClientクラスをインポートする
HttpClientサービスを利用するために、まずは、ルートモジュールからHttpClientModuleモジュールを有効にしておきます。これには、app.module.tsファイル(メインモジュール)で、@NgModuleデコレーターのimportsパラメーターにHttpClientModuleを追加してください。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule, FormsModule, HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
(2)コンポーネントからHttpClientサービスを呼び出す
HttpClientサービスを有効化できたところで、コンポーネントから実際に呼び出してみましょう*3。
*3 本稿では、簡単化のために、コンポーネントからHttpClientサービスを直接呼び出していますが、望ましいコードではありません。実際のアプリでは、HTTP通信のコードはサービスとして切り出すようにしてください。
import { Component } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
@Component({
selector: 'app-root',
template: `
<form>
<label for="name">名前:</label>
<input id="name" name="name" type="text" [(ngModel)]="name" />
<input type="button" (click)="onclick()" value="送信" />
</form>
<div>{{result}}</div>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = ''; // 入力された名前
result = ''; // 最終的に生成されるメッセージ
// [1]HttpClientサービスを注入
constructor(private http: HttpClient) { }
onclick() {
// [2]リクエストを発信
this.http.get('app/http.php', {
responseType: 'text',
// [3]URLにクエリパラメーターを指定
params: new HttpParams().set('name', this.name),
})
.subscribe(
data => {
this.result = data
},
error => {
this.result = '通信に失敗しました。';
}
);
}
}
コンストラクター経由でHttpClientサービスを注入できる点は、他のサービスを利用する場合と同じです(詳しくは、別稿「TIPS:自作のサービスを定義するには?」も参照してください)。コンポーネントのhttpプロパティにインスタンスをセットしておきます([1])。
実際にリクエストを発信しているのは、[2]です。getメソッドはHTTP GETメソッドでサーバーにリクエストを送信し、subscribeメソッドで応答データを処理します。
client
.get(url [,options])
.subscribe(
data => { success_callback },
error => { error_callback } )
引数optionsには「オプション名: 値」のハッシュとして、リクエストオプションを指定します。利用できるオプションについては、本連載でおいおい紹介していくとして、本稿で利用しているオプションのみ、以下でまとめておきます。
オプション | 概要 |
---|---|
responsType | 応答の型(blob、json、textなど。デフォルトはjson) |
params | クエリ情報 |
本稿で利用しているリクエストオプション |
paramsオプションには、HttpParamsオブジェクトを渡します。[3]ではnameキー(値はthis.name)だけを設定していますので、「〜http.php?name=入力値」のようなURLが生成されます。値にマルチバイト文字が含まれている場合にも、内部的にエンコード処理されるので、アプリ側では意識しなくて構いません。
subscribeメソッドの第1引数は、通信が成功した場合に実行されるコールバック関数を表します。引数として、レスポンス本体を受け取るので、本稿では、これをそのままresultプロパティに代入し、ページに反映しています。
第2引数は、通信が失敗したときに実行されるコールバックです。引数としてエラー情報(HttpErrorResponseオブジェクト)を受け取ります。ここでは固定のメッセージを表示しているだけですが、HttpErrorResponseオブジェクトを介してステータス値(status)やエラーメッセージ(message)を取得することも可能です。
(3)サーバーサイドのコードを準備する
HttpClientサービスからのリクエストを受け取るサーバーサイドのコードは、以下の通りです。本稿の守備範囲を超えるので、詳しい説明は割愛します。コード内コメントからおおよその意味を把握してください。
<?php
// クエリ情報nameを取得
$r = $_GET['name'];
// クエリ情報nameが空の場合はエラー
if (empty($r)) {
header('HTTP/1.1 500 Internal Server Error');
} else {
// 空でなければ、メッセージを出力
print('Hello,'.$r.'!');
}
(4)Apacheなどのサーバーに配置する
本稿のサンプルは、サーバーサイドでPHPを利用しているため、Angular CLI標準の開発サーバーでは動作しません。以下のようにアプリをビルドします。
> ng build
Date: 2018-02-06T08:02:46.345Z
Hash: 632fd435be0740ca688b
Time: 12651ms
……中略……
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.85 MB [initial] [rendered]
/distフォルダーにビルド結果が出力されるので、その配下にapp/http.phpをコピーします。
(5)基底パスを変更する
/distフォルダー配下のindex.htmlを開いて、<head>要素の中にある<base>要素を書き換えます。
<base href="/dist/" />
以上で準備は完了です。あとは、/distフォルダーをApacheの/htdocsフォルダーに丸ごと配置すれば、「http://localhost/dist/」でアプリにアクセスできます。
処理対象:サービス(Service) カテゴリ:基本
処理対象:クラス(CLASS) カテゴリ:サービス(Service)
API:HttpClient カテゴリ:@angular > common > CLASS(クラス)
Copyright© Digital Advantage Corp. All Rights Reserved.