Backbone.jsのModel.fetch で RESTful API から情報取得


Backbone.jsの特徴にRESTful APIとの親和性の高さがあります。
[Backbone.Model](http://backbonejs.org/#Model)はリソースのAciteveRecordです。
はじめの一歩としてRESTful APIから情報取得します。

# 準備
## 依存ライブラリ
Backbone.jsはjQueryとunderscoreに依存しています。
準備を簡単にするために、各ライブラリをCDNから取得します。

```html
<head>
  <script src="https://code.jquery.com/jquery-2.2.2.js" integrity="sha256-4/zUCqiq0kqxhZIyp4G0Gk+AOtCJsY1TA00k5ClsZYE=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
</head>

```

## RESTful API
[JSONPlaceholder - Fake online REST API for developers](http://jsonplaceholder.typicode.com/)を使います。
http://jsonplaceholder.typicode.com/posts/1 からリソースを取得します。

# 情報取得
## ソースコード

```html
<head>
  <script src="https://code.jquery.com/jquery-2.2.2.js" integrity="sha256-4/zUCqiq0kqxhZIyp4G0Gk+AOtCJsY1TA00k5ClsZYE=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
  <script>
    const PostModel = Backbone.Model.extend({
      url: 'http://jsonplaceholder.typicode.com/posts/1'
    })

    new PostModel()
      .fetch()
      .done((post) => console.log(JSON.stringify(post)))
  </script>
</head>
```

## 説明
### urlプロパティ
Modelのurlを指定します。
Modelは1つリソースと対応します。idまで指定します。

複数のリソースを扱う場合は[Backbone.Colletion](http://backbonejs.org/#Collection)を使います。
今回は説明しません。

### fetchメソッド
fetchメソッドを使ってRESTful APIを呼び出します。
次のリクエストを生成します。

```
GET /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: null
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6,zh-TW;q=0.4,zh;q=0.2
```

### 結果の扱い方
Ajaxリクエストは非同期です。
結果の扱い方は2種類あります。

### Taskベース非同期パターン
[Deferred Object](http://api.jquery.com/category/deferred-object/)であるjqXHRを使って[Taskベース非同期パターン](https://msdn.microsoft.com/ja-jp/library/hh873175(v=vs.110).aspx)が使えます。

```js
new PostModel()
  .fetch()
  .done((post) => console.log(JSON.stringify(post)))
```


[jqXHR](http://api.jquery.com/jQuery.ajax/#jqXHR)ですので、コールバック関数の引数は

1. data
2. textStatus
3. jqXHR 

です。

### イベントベース非同期パターン
Modelはイベントを発火できます。
[イベントベースの非同期パターン](https://msdn.microsoft.com/ja-jp/library/wewwczdw(v=vs.110).aspx)が使えます。

#### changeイベント

```js
new PostModel()
  .on('change', (post) => {
    console.log(JSON.stringify(post))
  })
  .fetch()
```


https://github.com/jashkenas/backbone/blob/master/backbone.js#L594

```js
if (!model.set(serverAttrs, options)) return false;
```

Ajaxリクエストが成功し、レスポンスが取得するとモデルを更新し、`change`イベントが発火します。コールバック関数の引数は

1. モデル
2. fetchの第二引数で指定したオプション

です。


#### syncイベント

```js
new PostModel()
  .on('sync', (post) => {
    console.log(JSON.stringify(post))
  })
  .fetch()
```

https://github.com/jashkenas/backbone/blob/master/backbone.js#L596
またsyncイベントで更新を取得することもできます。

```js
model.trigger('sync', model, resp, options);
```

コールバック関数の引数は

1. モデル
2. 取得したデータ
3. fetchの第二引数で指定したオプション

です。

### 結果のJSON

いずれの方法でも次のjsonを表示します。

```
{"userId":1,"id":1,"title":"sunt aut facere repellat provident occaecati excepturi optio reprehenderit","body":"quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
```

https://github.com/jashkenas/backbone/blob/master/backbone.js#L430
Modelは`toJSON`メソッドを持っています。内部にデータを持つ`this.attributes`のコピーを返します。
`JSON.stringify`で呼び出すと、RESTful APIから取得したデータと同じJSONを取得できます。

```js
// Return a copy of the model's `attributes` object.
toJSON: function(options) {
  return _.clone(this.attributes);
}
```

# 感想
イベント毎にコールバック関数の引数が違うのが辛そうです。

# 関連記事
- [Backbone.jsでHello World （Backbone.Viewのサンプル）](http://qiita.com/ledsun/items/dde4f415205c888f54b4)
- [Backbone.jsでModelに対応するViewをつくる](http://qiita.com/ledsun/items/dac6e7595ea9f28d30d2)
- [Bakcbone.jsとBrowserifyを一緒に使う](http://qiita.com/ledsun/items/e6703e703d4b3e7df7d7)