MilkcocoaのStreamAPIと新メソッドHistoryAPIの比較


@n0bisukeです。　
この記事は[ジーズアカデミーアドベントカレンダー](http://qiita.com/advent-calendar/2015/gsacademy)の記事です。

先日ジーズアカデミーの授業でやった[Milkcocoa](https://mlkcca.com/)の話です。
(授業参加者は授業の補足資料的な感じで見てもらえたら幸いです。)

**授業関係なく読めると思います。**

MilkcocoaでStreamAPIを今までは使っていましたが、HistoryAPIというものが追加されていましたので紹介します。

## 何が違うのか

[ドキュメント](https://mlkcca.com/document/api-js.html)によると以下が大きな変更点のような気がします。

* 1.ソートの方法が直感的になった
* 2.タイムスタンプで期間を指定することができるようになった
* 3.eventが追加された。

以下で検証してみます・

## チャットサンプルで検証

基本のソースコードはこちらになります。

> https://github.com/milk-cocoa/chat/blob/master/index.html

これをもとに通常のStreamAPIと新しくできたHistoryAPIの比較をしてみます。

ちなみにデータは以下のものをあらかじめ入れています。
![](https://i.gyazo.com/4d28038704519be4fdd137dfbb62d289.png)

> "あいうえお"を順番に入れました。

このデータをもとにStreamとHistoryの比較をしてみます。

### 1. ソート方法

使い方も変わってるみたいですが、ソートが大きく変わってるみたいです。

#### 1.1. StreamAPIのソート (従来)
![](https://i.gyazo.com/3ff2be7fd7a02deec220f9773a00f771.png)
今までのStreamAPIでのソートの場合は **取得する方向は変えずに取得**していました。

* DESC (降順)
https://github.com/milk-cocoa/chat/blob/master/index.html#L22-L27

![](https://i.gyazo.com/7af9159607c4db0e4838e6c00585e6c0.png)

* ASC (昇順)

`desc`の部分を`asc`に変更

```
ds.stream().sort("asc").next(function(err, datas) {
	datas.forEach(function(data) {
		renderMessage(data);
    });
});
```

![](https://i.gyazo.com/7af9159607c4db0e4838e6c00585e6c0.png)

しかし、結果は変わらず。

なぜこうなるのかというと、StreamAPIでは取得し始める場所が違うだけで **取得する方向は変えずに取得**しているため、データストアのデータをすべて取り出してしまうと、ソートが実行されているのかどうか分からないという問題がありました。 `sizeメソッド`などで件数を指定すると細かい挙動も見れます。

#### 1.2 HistoryAPIのソート (new!)

![](https://mlkcca.com/img/document/api/datastore-history-sort.png)
**たぶんみなさんが思い描いてるソートです。**

StreamAPIをHistoryAPIの書き方に書き換えてみましょう。

* DESC(降順)

![](https://i.gyazo.com/e00b6370eb2a0406908aba68ea0bae65.png)

```
        //3."message"データストアからメッセージを取ってくる
        var history = milkcocoa.dataStore('message').history();
        history.sort('desc').size(100);
        history.on('data', function(datas) {
            datas.forEach(function(data){
              renderMessage(data);
            });
        });
        history.on('end', function() {
            console.log('end');
        });
        history.run();
```

* ASC (昇順)

![](https://i.gyazo.com/7af9159607c4db0e4838e6c00585e6c0.png)

```
        //3."message"データストアからメッセージを取ってくる
        var history = milkcocoa.dataStore('message').history();
        history.sort('asc').size(100);
        history.on('data', function(datas) {
            datas.forEach(function(data){
              renderMessage(data);
            });
        });
        history.on('end', function() {
            console.log('end');
        });
        history.run();
```

ちゃんと昇順と降順でうまい具合にデータが逆転していることが分かると思います。

### 2. タイムスタンプで期間を指定

今まで期間指定をして検索をするAPIが無かったですが、これでもっと面白いアプリが出来そうです。

```
var history = milkcocoa.dataStore('message').history();
// 2015/10/30-2015/11/3のpush()で保存したデータを取得
history.span(new Date(2015,9,30).getTime(), new Date(2015,10,3).getTime());
```

実際、**特定の日の情報や1ヶ月間の情報を取得したいときって多い**気がしますね。

### 3. eventが追加された

Streamにはonメソッドは無いですが、Historyにはonメソッドがあり、イベントを監視できます。

* `on('data')`: size()で指定したデータ数を取得した都度呼ばれます。コールバックにデータが返ってきます。
* `on('end')`: limit()またはspan()で指定したデータ数や期間分の全てのデータを取得し終わったら呼ばれます。
* `on('error')`: エラーが起こったら呼ばれます。コールバックにはエラーオブジェクトが返ってきます。

こんな感じです。(ドキュメントより)

データが全て取得し終わったら呼ばれるのはいいですね。

## まとめ

HistoryAPIを調べれば調べるほどStreamAPI側の上位互換になってる気もします笑

とくに意識しないのであればMilkcocoaでのデータ取得はHistoryAPIを使って実装していったほうがいいかもしれませんね。