Humanity

Edit the world by your favorite way

Angular の $http, $resource が返す promise で受け取れる値

Angular 使ってて今更だけど $http$resource が返す promise で受け取れる引数が違って混乱したのでまとめてみた。

$http

まず $http の場合は resolve(), reject() された値を受け取る方法として2通りある。

  1. $http(...).then(successCallback, errorCallback) で受け取る
  2. $http(...).success(successCallback)$http(...).error(errorCallback) で受け取る

1の場合の callback の引数は以下の通り (ソース:公式ドキュメント)。

  1. response – Object
    • data – {string|Object} – The response body transformed with the transform functions.
    • status – {number} – HTTP status code of the response.
    • headers – {function([headerName])} – Header getter function.
    • config – {Object} – The configuration object that was used to generate the request.
    • statusText – {string} – HTTP status text of the response.
$http.get().then(function onSuccess(res) {
  // res.data, res.status, res.headers, res.config, res.statusText
  // ...
}, function onError(res) {
  // res.data, res.status, res.headers, res.config, res.statusText
  // ...
});

// error の場合はこう受け取っても構わない。
// こっちのが本来(?)の Promise と同じインターフェースなのと例外処理な感じがして好き。
$http.get().then(function onSuccess(res) {
  // ...
}.catch(function onError(res) {
  // ...
});

2の場合の callback の引数は以下の通り。 1の場合のオブジェクトがフラットに渡される感じ (statusText 以外)。

  1. data – {string|Object} – The response body transformed with the transform functions.
  2. status – {number} – HTTP status code of the response.
  3. headers – {function([headerName])} – Header getter function.
  4. config – {Object} – The configuration object that was used to generate the request.
$http.get().success(function onSuccess(data, status, headers, config) {
  // ...
}).error(function onError(data, status, headers, config) {
  // ...
});

ただ説明した後でアレだけど、2の success()error() は deprecated とされているので使わない方がいい。 既存コードで使われているのを見たら渡される引数の違いを意識した方がいいということ。

ちなみに以下のようにして success()error() を使ったらエラーにできる (useLegacyPromiseExtensions はデフォルト true)。

angular.module('sample')
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.useLegacyPromiseExtensions(false);
  }]);

$resource

$resource は内部で $http を使っているが、インターフェースが若干違う。 まず Resource.post(parameters, successCallback, errorCallback)Resource.get(successCallback, errorCallback) などのようにメソッドに直接コールバックを指定する場合。 以下公式ドキュメントからの引用。 (get() などの場合は parameters を省略できます。正確な引数の順番や受け取り方はソース見たほうが早い)

  1. HTTP GET "class" actions: Resource.action([parameters], [success], [error])
  2. non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
  3. non-GET instance actions: instance.$action([parameters], [success], [error])

ここで "class" や "instance" と言っているのは以下の違い。 まずリクエストを送る時は以下のようにリソースを定義する必要がある。

// Define CreditCard class
var CreditCard = $resource('/user/:userId/card/:cardId',
 {userId:123, cardId:'@id'}, {
  charge: {method:'POST', params:{charge:true}}
 });

class

CreditCard.query(parameters, function onSuccess(data, headers) {
  // ...
}, function onError(res) {
  // ...
});

instance

var instance = new CreditCard(parameters)
instance.query(function(data, headers) {
  // ...
}, function onError(res) {
  // ...
});

また、"class" と "instance" 経由で取得する以外に $promise 経由で取得する方法がある。

CreditCard.query(parameters).$promise.then(function onSuccess(data, headers) {
  // ...
}).catch(function onError(res) {
  // ...
});

ちなみに (追記)

Angular で async/await を使う際は自動で $scope.$apply() が呼ばれないのでこういうの使うといいみたいです。

以上

ここまで書いといてなんだけど、公式ドキュメント見た方がいい。