Angularでサーバーサイドと「非同期通信」するには?(HttpClientサービス)Angular TIPS

HttpClientサービスを使ってWeb APIと非同期通信するための基本的な方法を説明する。

» 2018年03月19日 05時00分 公開
[山田祥寛]
「Angular TIPS」のインデックス

連載目次

現在では、Web標準技術を利用したアプリ開発が広く普及し、そのためのフレームワークも多数存在しています。その中でも主流のフレームワークの1つである「Angular」を活用し、そのための知識を備えることには大きな意味があります。本連載は、Angularユーザーに向けて、その使いこなしTIPSを紹介するものです。なお、本連載は「Build Insider」で公開していた連載「Angular Tips」を同サイトおよび筆者の了解を得たうえで、本フォーラムに移行したものです。記事はBuild Insiderで公開した状態のまま移行しているため、用語統一などの基準が@ITの通常の記事とは異なる場合があります。


【対応バージョン】

 Angular 5以降。v5時点で執筆しました。


 近年のフロントエンド開発において、非同期通信を受け持つXMLHttpRequest(XHR)オブジェクトは欠かせません。JavaScript単体でできることは限られています。JavaScriptアプリでは、ページ上の操作に応じてXHRでサーバーに処理を要求し、その処理結果をページに反映させるのが基本です*1

*1 このようなアプリのことを、単一のページで全ての処理を完結させることから、SPASingle Page Application)と呼びます。


 HttpClientサービス*2は、このXHRオブジェクトのラッパーです。HttpClientサービスを利用することで、XHRオブジェクトでは冗長になりがちだった通信の手続きを、よりシンプルに記述できるようになります。

*2 以前は@angular/httpモジュールに属するHttpサービスがありましたが、Angular 5では非推奨の扱いとなっています。今後はHttpClientサービスを優先して利用してください。


 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 { }

HttpClientModuleモジュールをインポートするコード(app.module.ts)

(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サービスでサーバーサイドに問い合わせるコード(app.component.ts)

 コンストラクター経由でHttpClientサービスを注入できる点は、他のサービスを利用する場合と同じです(詳しくは、別稿「TIPS:自作のサービスを定義するには?」も参照してください)。コンポーネントのhttpプロパティにインスタンスをセットしておきます([1])。

 実際にリクエストを発信しているのは、[2]です。getメソッドはHTTP GETメソッドでサーバーにリクエストを送信し、subscribeメソッドで応答データを処理します。

[構文]HttpClientクラス(getメソッド)

client
  .get(url [,options])
  .subscribe(
    data => { success_callback },
    error => { error_callback }   )

  • client: HttpClientサービス
  • url: リクエスト送信先のアドレス
  • options: リクエストオプション
    • success_callback: 通信に成功した場合の処理
    • error_callback: 通信に失敗した場合の処理

 引数optionsには「オプション名: 値」のハッシュとして、リクエストオプションを指定します。利用できるオプションについては、本連載でおいおい紹介していくとして、本稿で利用しているオプションのみ、以下でまとめておきます。

オプション 概要
responsType 応答の型(blobjsontextなど。デフォルトは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.'!');
}


クライアントからの要求を受けてメッセージを出力するコード(http.php)

(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/" />

基底パスを変更(index.htmlから抜粋)

 以上で準備は完了です。あとは、/distフォルダーをApacheの/htdocsフォルダーに丸ごと配置すれば、「http://localhost/dist/」でアプリにアクセスできます。

処理対象:サービス(Service) カテゴリ:基本
処理対象:クラス(CLASS) カテゴリ:サービス(Service)
API:HttpClient カテゴリ:@angular > common > CLASS(クラス)


「Angular TIPS」のインデックス

Angular TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。