TwitterやQiitaのような自動更新タイムラインをBackbone.jsで作成
Qiitaでは新しい投稿がある場合にその件数を表示し,クリックするとタイムラインに追加するということをやっています.TwitterやFacebookと同じ仕組みですね.
これはBackbone.jsのBackbone.Collection#fetchを使うと簡単に実装できます.
便利な機能ですね!
Ember.jsでもfetchを実装してみました。
ソース:
https://github.com/kmdsbng/emberjs_fetch_sample/blob/master/js/app.coffee
ソースコードを抜粋します。
App.tweets = Ember.ArrayController.create Ember.Fetchable,
content: [],
maxId: 3, # adhoc
url: (->
'./item.json?after=' + @get('maxId')
).property('maxId'),
Controllerをcreateする際に、Ember.FetchableというMixinを継承するように指定します。
すると、Controllerインスタンスにfetchメソッドが生えます。
fetchメソッドはアイテムを取得するために url メンバを使用します。今回はafter以降のidのアイテムを取得するURLを生成するように指定しています。
setInterval((->
if App.tweets.get('recentCount') < 10
App.tweets.fetch()
), 5000)
5秒ごとに新着情報を取得します。結果はApp.tweets.contentに追加されます。
次はテンプレートを見てみます。
<script type="text/x-handlebars" data-template-name="twitter_list">
{{#if view.hasRecentItems}}
<button {{action expandRecent}}>新着{{view.recentCount}}件を表示する</button>
<br>
{{/if}}
<ul>
{{#each view.items}}
<li>
<b>
[{{id}} {{title}}]
</b>
<br>
{{body}}
</li>
{{/each}}
</ul>
</script>
新着情報があるときだけ、「新着XX件を表示する」ボタンを表示します。
QiitaやTwitterでも実装されてるアレです。
このあたりの機能もEmber.jsのデータバインディング機能を利用すればスッキリ書くことができていい感じです。
最後に Ember.Fetchable のコードを見てみましょう。
Ember.Fetchable = Ember.Mixin.create
fetchItems: ((max_id) ->
_this = @
return $.Deferred((defer) ->
return $.ajax(
url: _this.get('url'),
dataType: 'json',
data:
after: max_id
).done((res) ->
return defer.resolve(res.results)
)
).promise()
),
fetch: ((callback) ->
_this = @
@fetchItems(@get('maxId')).done((tweets) ->
items = tweets.map((v) ->
v['recent'] = true
Ember.Object.create(v)
).reverse()
_this.get('content').unshiftObjects(items)
if callback
callback()
)
)
fetchItemsメソッドは、jQueryのajaxメソッドを利用して結果を取得してます。
fetchメソッドは取ってきた結果にrecentフィールドをセットし、contentに追加しています。
以下のページで実際の動作を確認することができます。