LoginSignup
4
2

More than 5 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 さんが担当です!
お願いします!

4
2
0

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
  3. You can use dark theme
What you can do with signing up
4
2