LoginSignup
8
11

More than 5 years have passed since last update.

【AngularJS】$resourceでmetadataをいいカンジに扱う

Last updated at Posted at 2015-04-21

$resourceでmetadataをいいカンジに扱う

TL;DR

'transformResponse': function (data, headersGetter) {
  var result = angular.fromJson(data);
  result.data.$metadata = result._metadata;
  return result.data;
},
'interceptor': {
  'response': function (response) {
    response.resource.$metadata = response.data.$metadata;
    return response.resource;
  }
}

WHAT

以下の様なレスポンスを返すAPIがあるとする.

{
  "data": [
    { "id": 1, "content": "kokoro pyonpyon" },
    { "id": 2, "content": "Ah^~ my heart will be hopping^~" }
  ],
  "_metadata": {
    "total": 53,
    "nextPage": 2
  }
}

普通にtransformResposne通すだけだと,_metadataが落ちてしまう.
あとのコールバックで_metadataを利用したいのでそれは困る.

HOW

transformResponseの返り値に$metadataをつっこみ,interceptor内でresourceに押し付ける.

var app = angular.module('app', ['ngResource']);

app.factory('Post', [
  '$resource',
  function ($resource) {
    var endpoint = 'api/v1/posts/:id';
    var params = {};
    var actions = {
      'query': {
        'method': 'GET',
        'isArray:' true,
        'transformResponse': function (data, headersGetter) {
          var result = angular.fromJson(data);
          result.data.$metadata = result._metadata;
          return result.data;
        },
        'interceptor': {
          'response': function (response) {
            response.resource.$metadata = response.data.$metadata;
            return response.resource;
          }
        }
      }
    };

    $resource(endpoint, params, actions);
  }
]);

動作の流れ

上記のコードでは,デフォルトの代わりに利用するinterceptorを定義している.
src/ngResource/resource.js#L558-L559 from angular/angular.js

// src/ngResource/resource.js#L558-L559
var responseInterceptor = action.interceptor && action.interceptor.response ||
  defaultResponseInterceptor;

デフォルトのinterceptordefaultResponseInterceptor)ではresponse.resourceを返すようになっている.
src/ngResource/resource.js#L497-L499 from angular/angular.js

// src/ngResource/resource.js#L497-L499
function defaultResponseInterceptor(response) {
  return response.resource;
}

response.resourceにはAPIのレスポンスをResourceでラップしたものが入っていて,それが最終的に呼び出し元に返される.
ということで,response.resource$metadataを押し付けておけば後から取り出してほげほげできるというわけ.

image

Railsでいうindexライクな,リストを返すAPIが上記の形式({ "data": [...], "_metadata": {...} })で統一されているならば,transformResponseinjectorをうまくサービス化してDRYにできるかもしれない.
transformResponseinterceptorを使いこなしたイケてるコードを書こう.

REF

8
11
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
8
11