余白

https://blog.lacolaco.net/ に移転しました

なぜAngularJSに$httpが必要だったのか(あるいはAngular HttpClientの価値について)

lacolaco.hatenablog.com

「レールに乗っておいたほうがいいんじゃないの?」という声もあるとおもうので、 そもそもなぜAngularはHTTPクライアント機能をスタックとして提供しているのか、というところについて。

AngularJSには$httpが必要だった

遡ってAngularJSの話をすると、AngularJSにも組み込みのHTTPクライアント機能があり、そのAPI名からよく$httpと呼ばれています。

https://docs.angularjs.org/api/ng/service/$http

現在ではこんな感じのAPIになっています。

// Simple GET request example:
$http({
  method: 'GET',
  url: '/someUrl'
}).then(function successCallback(response) {
    // this callback will be called asynchronously
    // when the response is available
  }, function errorCallback(response) {
    // called asynchronously if an error occurs
    // or server returns response with an error status.
  });

この機能がAngularJSに必要だった理由は以下のダイジェストループによるものが大きいです。

AngularJSのダイジェストループ

AngularJSは内部のダイジェストループが繰り返し実行されることでコントローラーの変更がビューに反映されます。 一般にHTTPのレスポンスが返ってきたあとにはコントローラーの状態が変わり、取得した値を表示することになるので、 HTTPクライアントがAngularJSのダイジェストループをトリガーできる必要がありました。

必要がありました、とはいえ、AngularJSに詳しければ $scope.$applyAsync使えばいいじゃん、というのはありますし、それは正しいです。 しかしXHRが発火するさまざまなイベントのなかで適切にダイジェストループを回すのは難しく、 ダイジェストループのオーバーヘッドは大きいのでうまく出来ないとパフォーマンスが悪化する危険性もあります。

なので、簡単に使えるようにするために、AngularJSのコアと密接なHTTPクライアントが必要でした。

jQuery$.ajax

当時主流だった $.ajax と似たAPIを持つことで、導入の障壁を下げる狙いもあったかもしれません。

AngularのHttpClientはなんのためにあるのか

そうしたAngularJSの背景をもとに、今のAngularのHttpClientにはどういった価値があるのかを改めて考えることができます。

Change DetectionとZone.js

Angularにはダイジェストループはなく、ランタイムで発生するほぼすべての非同期処理はZone.jsによって捕捉され、Angularの変更検知システムへディスパッチされます。 XHRを使おうと、Fetch APIを使おうと、非同期処理の終了後にはデータバインディングに基づいてビューが更新されます。

つまり、ビュー描画システムとしてのAngularと、AngularのHTTPクライアントは完全に分離可能だということです。

RxJS親和性

ではなぜAngularのHTTPクライアントが存在するのか、それはPromiseではなくObservableベースのHTTPクライアントを導入するためです。 Angularはコアの非同期処理から周辺モジュールまで、多くの非同期処理をRxJSのObservableベースで実装しています。 そのため、HTTPクライアントのAPIもObservableを返すように実装されていたほうが、アプリケーション全体でRxJSの恩恵を受けることができます。

RxJSに精通し、使いこなせる開発者にとっては、非常に強力な武器になるAPIなのは間違いないです。 そしてXHRの各種イベントをわかりやすいAPIとしてRxJSで実装するのは骨が折れるので、この部分がAngular公式に提供されていることが最大の価値です。

フルスタックの信頼性

フルスタックであることでモジュール選択のコストをさげることが目的の場合には迷わず選択できる公式パッケージには大きな意味があるでしょう。

いつAngular HttpClientを使わないのか

想像するに次のような場面でサードパーティや独自実装のHTTPクライアントを採用するモチベーションがあると思います。

  • RxJSの学習コストを下げたい
    • JavaScript自体の練度が低い場合、Promiseもわからない状態でObservableに手を出すのはハードルが高いでしょう
    • あるいはRxJSをアプリケーションコードでは書きたくないという好みの問題もありでしょう
  • すでにサードパーティHTTPクライアントの知見を持っており、流用できる
    • お気に入りのものがあればそれを使ってよいと思います。

まとめ

  • AngularJSの$httpとAngularのHttpClientは立場が違う
    • $http はどうしても必要だった
  • RxJSとどう付き合うかで考えるとよい
  • お気に入りのライブラリがあるならそれを使って楽しく開発するのがよい