体感!JavaScriptで超速アプリケーション開発 -Meteor完全解説

第11回 データ同期とリアクティブ・プログラミング

この記事を読むのに必要な時間:およそ 4 分

今回は,前回に引き続きMeteorのリアクティブ・プログラミングについて説明します。

Meteorアプリケーションでは,あるクライアント上で行ったデータ変更が,他のクライアントにもリアルタイムに伝わります。しかも,そのために必要なコードはごくわずかで,ほぼ自動的に処理されるといっても過言ではありません。

その仕組みは,⁠クライアント上のリアクティビティ」と,⁠publish/subscribeによる,サーバデータとクライアントキャッシュの同期」によって実現されています。

前回,クライアント上でのリアクティビティについてはお伝えしました。今回はpublish/subscribeについて解説し,リアクティビティについても復習します。

publish/subscribeによるデータ同期

Meteorでは,サーバ上のデータはクライアントにキャッシュされ,リアルタイムに同期されます。同期は自動的に,しかも双方向に行われるため,開発者が明示的に同期処理を記述する必要はありません。必要とされるのは,Meteor.publish()Meteor.subscribe()を使用し,データを同期する範囲を指定することだけです。

図1 publishとsubscribe

図1 publishとsubscribe

publishsubscribeの説明のため,まずは前提条件として,⁠従業員データ」を格納する以下のようなコレクションがあると仮定します。このコレクションは,クライアントとサーバの双方でインスタンス化されます。

var Employees = new Meteor.Collection('employees');

サーバ側で実行されるMeteor.publish()は,名前を表す文字列と,関数オブジェクトを引数に取ります。

Meteor.publish("emp", function () {
    // 60歳以上の従業員データを返す
    return Employees.find({ age: { $gte: 60 }});
});

引数として渡す関数オブジェクトは,データのコレクションを戻り値として返します。この戻り値となったコレクションが,クライアント側のキャッシュと自動的に同期されます。上の例では,60歳以上の従業員データが返されます。

対してMeteor.subscribe()はクライアント側で呼び出され,publishによって公開されたデータを「購読」⁠同期して取り込むこと)します。

Meteor.subscribe('emp');

ここに挙げた例では,サーバデータのうち「60歳以上」のデータのみが,クライアントのコレクションに同期されます。

publishsubscribeは,Meteorプログラミングにおいては非常に重要なAPIです。以降では,これらのAPIについてさらに詳しく説明します。

Meteor.publish()

Meteor.publish()の定義は以下のとおりです。

Meteor.publish(name, func)
  • name…名前を表す文字列。クライアントがサブスクライブを行う際に,この名前が使用される。
  • func…この関数は,クライアントからのサブスクライブが行われるたびに呼び出されます。

第二引数funcの目的は,クライアント側のキャッシュと同期するデータ(コレクション)を指定にすることです。そのひとつの方法としては,コレクションのカーソルMeteor.Collection.Cursorを戻り値とすることです。上記の例を再掲します。

Meteor.publish("emp", function () {
    // 60歳以上の従業員データを返す
    return Employees.find({ age: { $gte: 60 }});
});

もうひとつの方法としては,publish内でコレクションに変更を行い,その旨をクライアントに通知することです。こうした操作は,publish内のthisオブジェクトが持つ以下のようなメソッドを通じて行います。

added(collectionName, id, fields)
…コレクション名,ドキュメントのID(_idフィールド)⁠追加されたドキュメント(JavaScriptオブジェクト)を引数に取り,ドキュメントが追加されたことをクライアントに通知します。
changed(collectionName, id, fields)
…コレクション名,ドキュメントのID(_idフィールド)⁠変更されたドキュメント(JavaScriptオブジェクト)を引数に取り,ドキュメントが変更されたことをクライアントに通知します。
removed(collectionName, id)
…コレクション名,ドキュメントのID(_idフィールド)を引数に取り,ドキュメントが削除されたことをクライアントに通知します。

また,publish内のthisオブジェクトは,以下のようなメソッドも保持しています。

userId
…ログインユーザのID。ログインされていなければnull。
ready()
…クライアントに対し,初期データの送信が終わったことを伝える。Meteor.subscribe()のコールバックが呼び出される。
onStop(func)
…パブリッシュが停止した際に呼び出されるイベントハンドラを登録する。
error(error)
…クライアントにエラーを通知する。クライアントからのサブスクライブは停止し,Meteor.subscribe()のコールバックが呼び出される。
stop()
…パブリッシュを停止する。

また,funcは引数を取ることもできます。funcに引数として渡される値は,クライアントがMeteor.subscribe()で渡したものになります。よくある例としては,クライアントが検索条件などを指定してサブスクライブを行う場合に,検索条件を渡す用途で使用されます。

著者プロフィール

白石俊平(しらいししゅんぺい)

株式会社オープンウェブ・テクノロジー代表取締役

HTML5開発者コミュニティhtml5j.org管理人

HTML5とか勉強会主催

Web先端技術味見部 部長

読書するエンジニアの会主催

しろうと哲学部 部長

Google API Expert(HTML5)

Microsoft Most Valuable Professional 2010, 2011(Internet Explorer)

コメント

コメントの記入