Sunday, July 13, 2014

backbone.iobind

backbone.ioの使い方メモ.

backbone.iobind

socket.ioと一緒にインタラクティブなWebAPIを作れるって言うから試してみた. 今更だけど無理に使わずに普通にsocket.io入れてもよかったかもしれない…

Model, Collection

iobindはModelまたはCollectionに対してsocket.io由来のイベントとの結びつけを行う. ViewはModel, Collectionで発生したイベントを経由して表示を更新する.

initialize

iobindの公式を見ると2種類のbindを使っている.

   initialize: () ->
      _.bindAll(@, "serverChange", "serverDelete")

      if(!@noIoBind)
        @ioBind('update', window.socket, @serverChange, @)
        @ioBind('delete', window.socket, @serverDelete, @)
一個目: _.bindAll

@(this)に対してserverChange, serverDeleteメソッドを結びつける. これにより、このコンテキストの外でserverChange, serverDeleteが呼ばれてもserverChange, serverDeleteが参照する@(this)は,bindAllの第一引数で指定した「@(this)」になる.

うぅ…ややこしぃ…

二個目: @ioBind

backbone.iobindで追加された関数. 第一引数で指定したsocket.ioのイベント受信時に実行する関数を割り当てる.

それぞれ次のような意味になる.

  • update を受信したらserverChange
  • delete を受信したらserverDelete

実際にserverChange, serverDeleteが実行されるときのthisは_.bindAllで指定した@(this)になっているはずなので、意図通りの処理が出来るはず.

View

Viewについてbackbone.iobindで追加される要素はない. Model, Collectionで発生したsocket.io由来のイベントをトリガーにしてページの更新を行う.

    initialize: (recipebook) ->
        #@listenTo @model, 'change', @render
        _.bindAll(@, 'render', 'addRecipe')

        @recipebook = recipebook

        @recipebook.bind('add', @addRecipe)

Viewのコンスタクタ.

Collection要素のrecipebookに対してaddがコールされた時にaddRecipeの実行がトリガされるように指定. Model, Collectionの時と同じように関数実行時のthisをあらかじめ束縛する.

イベントの種類

create, read, update, deleteのどれか.

Model, Collectionのsave, destroyと直で結びつけているから変えようがないみたい.

save, destory実行時にBackbone.syncが呼ばれ、第一引数のmethodに上記に挙げた4種類のイベントのどれかが入ってくる.

Backbone.sync

iobindを導入するとBackbone.syncをsocket.io用に置き換えてくれる. 色々書いてあるけど、大事なところは下の箇所かな?

  var defer = $.Deferred();
  io.emit(namespace + ':' + method, params.data, function (err, data) {
    if (err) {
      if(options.error) options.error(err);
      defer.reject();
    } else {
      if(options.success) options.success(data);
      defer.resolve();
    }
  });
  var promise = defer.promise();
  model.trigger('request', model, promise, options);
  return promise;

io.emit(…)で接続先のwebsocketサーバにデータを送っていて、この結果が失敗か成功かで処理を分ける…ようなことを呼び出し側に期待しているんだろうな(確認までしていない)

Backbone.sync(...)
.done( ->
  #do something at scuuess
).fail( ->
  #do something at fail
)

テスト

socket.ioがらみの効率的なテスト方法を調査中.

通信部分をスタブに置き換えてあげるしかないかな. 現在は適当に立ち上げたサーバーと通信させているけど、なぜか同じメッセージがサーバーから複数回送られてきたりとかなり不安定.

Backboneのメモ

trigger

Eventsモジュールにtriggerという便利な(探していた)関数がある. 他にonも多用しそう. 後で詳しく見ておこう.

triggerobject.trigger(event, [*args]) 

Trigger callbacks for the given event, or space-delimited list of events. Subsequent arguments to trigger will be passed along to the event callbacks.

1 comment:

  1. coffee script => (ファットアロー)を使う場合、_.bindAll(obj, ...)は必要なさげorz

    ReplyDelete