LoginSignup
1

More than 3 years have passed since last update.

AngularのHttp -> HttpClientにした話

Last updated at Posted at 2018-12-03

この記事は、Business Bank Group Developers Advent Calendar 3日目の記事です。


こんにちは、ビジネスバンクグループでエンジニアをしているしみきょん @kyokoshimizu です。

今Angularのversionを6にアップデートしようとしているのですが、その前に必須となるHttp -> HttpClient 移行した話を書きます

移行作業

もともと、HttpModuleを使用してHTTPリクエストを行なっていた処理を、HttpClient, HttpClientModuleを使用するようにしました。

// import { HttpModule } from '@angular/http';
import { HttpClient, HttpClientModule } from '@angular/common/http';

もともと、こんな感じだったHTTPリクエスト用のServiceが

import { Headers, Http, URLSearchParams } from '@angular/http';

export interface HttpOptionsInterface {
  params: any;
  body: any;
  ...
}

export class BaseService {
  constructor(private http: HttpClient) {}

  search<Hoge>(url: string, options?: HttpOptionsInterface): Observable<Hoge> {
    const headers = this.getHeaders(options.header);
    const params = this.getSearchParams(options.params);

    return this.http.get(url, Object.assign({ headers: headers, params: params }))
      .map(res => res.json() as Hoge);
  }

  ...

  protected getHeaders(options: any = {}): Headers { ... } // 認証トークンやContent-Typeのセット
  protected getSearchParams(params: any): URLSearchParams { .. } // リクエストパラメータのセット
}

こんな感じに変わりました

import { HttpClient, HttpParams } from '@angular/common/http';

export interface HttpOptionsInterface {
  params: any;
  body: any;
  ...
}

export class BaseService {
  constructor(private http: HttpClient) {}

  search<Hoge>(url: string, options?: HttpOptionsInterface): Observable<Hoge> {
    return this.http.get<Hoge>(url, { params: this.getSearchParams(options.params) });
  }

  ...

  protected getSearchParams(params: any): HttpParams { .. }
}

レスポンスがJSONオブジェクトとして返却されるようになりました

そのため、レスポンスを.jsonする必要がなくなりました。
またメソッドを呼ぶ際に型パラメータを指定することによって、レスポンスオブジェクトの型定義もできます。

this.http.get<Hoge> // -> Observable<Hoge>

responseTypeを指定することによって、JSON以外のデータをリクエストすることも可能です。
リクエスト処理が失敗した時は、HttpErrorResponseが返却されます。

リクエスト周りの変更点

Headers -> HttpHeaders
URLSearchParams -> HttpParams

になりました。
HttpParamsはimmutableです。
HttpParamsOptionsというオプションがあって

  new HttpParams({fromObject: { hoge: 1, hoge: 2 }})

みたいなことができるのですがAngular5以降しかfromObjectオプションがないので、Angular4環境で作業していた私は使用できませんでした。。

string, 配列, オブジェクトの3パターンの値をHttpParamsにセットしたかったので現状こんな感じになってます
(Angular6にしたらリファクタリングする予定です)

let urlSearchParams = new HttpParams();
_.each(params, (val, key) => {
  if (val instanceof Array) {
    _.each(val, (v) => urlSearchParams = urlSearchParams.append(key.toString(), v));
  } else {
    const value = (val instanceof Object) ? JSON.stringify(val) : val;
    urlSearchParams = (_.isUndefined(value) || _.isNull(value)) ?
      urlSearchParams.delete(key.toString()) : urlSearchParams.append(key.toString(), value);
  }
});

RequestOptionsArgsはなくなり、HttpClient#get, HttpClient#deleteにはbodyを渡せなくなったのでgetやdeleteにbodyを渡したい時は、HttpClient#requestを使用するようにしました。

Interceptor

インターセプターという機能が追加されました。
HttpInterceptorを実行したclassにinterceptメソッドを書くと、リクエストとレスポンス時に処理をフックすることができます。
今回は、もともとgetHeadersで行なっていたheader情報の挿入をinterceptorに切り出しました。

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';

@Injectable()
export class DefaultRequestInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const newReq = req.clone({
      setHeaders: { 'Content-Type': 'application/json' }
    });
    return next.handle(newReq);
}

interceptor便利です!

まとめ

以上、HttpClient移行の話でした。インターセプターは今後も色々と活用していきたいなと思います!
日本語公式ドキュメント 丁寧に説明されていてわかりやすかったです

明日は、 @bigplants さんが担当です!
お願いします!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1