読者です 読者をやめる 読者になる 読者になる

Umi Uyuraのブログ

Titaniumを使ったスマートフォンアプリ開発を中心に、プログラミング関連の作業ログ。

Alloy Modelの学習・その4(REST API)の続き

前回、REST APIのData Bindingを使ってみたのですが、

umi-uyura.hatenablog.com

そのときに課題として残していたエラーハンドリングなどレスポンスに対する処理に関してと、開発中にAPIエンドポイントを分離したい場合の方法についてメモ。

レスポンスに対する処理

napp.alloy.adapter.restapi を使う際の、エラー処理を含むレスポンスの処理方法を調べてみました。

napp.alloy.adapter.restapiのリポジトリに掲載されている例では引数を受け取っていませんでしたが、各メソッドでは、以下のように successerror のコールバックを受け取ることができます。

function doOpen() {
  memos.fetch({
    success : function(models, response){
      Ti.API.debug('memo fetch() - success = ' + models + ' / ' + response);
    },
    error : function(models, response){
      Ti.API.debug('memo fetch() - error = ' + models + ' / ' + response);
    }
  });
}

successerror コールバックは、サーバーからのレスポンスのHTTPステータスコードによって判断されて呼びだされるため、基本的に意識する必要はありません。

受け取ったモデルの加工だったりエラーに対する処理のほか、通信中のローディング画面の制御などもここでハンドリングできますね。

コールバックの形

操作対象がCollectionなのかModelなのかによって、コールバックには大きく2種類の形があるようです。

メソッド コールバック コールバックの形
Collection.fetch() success
error
function(models, response)
Model.save()
Model.destroy()
success
error
function(model, response)

各コールバックの第1引数は、主に操作したモデルデータを受け取るようです。

次に、共通している response には、Titanium.Network.HTTPClientの responseText が入ってくるようです。通信をJSONでやりとりする場合は、必要に応じて JSON.parse() するなどして扱うことになると思います。

コールバックの形を見るに、 responseText 以外の情報は受け取っていないようなので、例えばもしアプリ側でもHTTPステータスコードが必要な場合は、あらかじめレスポンスボディに含めるなどする必要がありそうです。

iOSAndroidでエンドポイントを分ける

特にPCローカルのサーバーと、iOSAndroidのシミュレータ/エミュレータで通信確認をする場合のメモです。

iOSのシミュレータでは 127.0.0.1 で開発しているMac側で立ち上げているAlloyModelStudyRestStubにアクセスできるのですが、AndroidエミュレータやGenymotionの場合、 127.0.0.1 は端末自体を示すらしく、 10.0.2.210.0.3.2 といったIPになるようです。

モデルの URL を書き換えれば対応できますが、その都度実施するのも面倒なので、あらかじめ config.json に設定しておき、そのURLを使うようにしました。

app/config.json

{
  ...
  "os:android env:development": {
    "API_URL": "http://10.0.3.2:4321/memos"
  },
  "os:ios env:development": {
    "API_URL": "http://127.0.0.1:4321/memos"
  },
  ...
}

config.json で設定できる値は、 os:androidos:ios といったプラットフォームをあらわすオブジェクトに、動作環境をあらわす env:development などを組み合わせることで、「Androidエミュレータの場合」「iOSエミュレータの場合」に使う値、というようにバリエーションをつけることができます。

それをモデルの中で参照することで、環境ごとに異なるURLを使えるようになりました。

app/models/memo.js

exports.definition = {
  config: {
    columns: {
      "id": "integer",
      "contents": "text",
      "priority": "text"
    },
    adapter: {
      type: "restapi",
      collection_name: "memo",
      "idAttribute": "id"
    },
    "URL": Alloy.CFG.API_URL,           // <== config.jsonに定義したURL
    "debug": 1
  },
  ...
};

env:production などと組み合わせれば、本番環境向けビルドで使うURLも設定できます。

なお、以前はモデルの中でグローバルな Alloy オブジェクトを参照できなかったので、こちらの記事( AlloyのModelでREST APIからデータを取得する - Qiita )のように一手間必要だったようですが、Alloy 1.4.0?あたりから参照できるようになったようです。

Backbone.js的な対処方法

モデル側のURLの指定を変更する方法とは別に、Backbone.js的に、モデル操作時にオプションとしてURLを渡すという対処方法もあります。

その場合は、 Collection.fetch({url: <url>})Model.save(<params>, {url: <url>})Model.destroy({url: <url>}) といったあたりのメソッドを使えば良いようです。

エンドポイントを動的に変更するようなケースがあれば、使いみちがあるかもしれません。

まとめ

APIのレスポンスに関しては、自前で用意するAPIであれば設計段階で調整できますが、既成サービスのものなどを使う場合はいじりようがないので、実戦使用するときに、また色々と検証しようと思います。

Appcelerator Titanium Smartphone App Development Cookbook - Second Edition

Appcelerator Titanium Smartphone App Development Cookbook - Second Edition